From localhost: 4200 I am trying to make a POST request, to my Slim REST API (3.0 v), which I have hosted on a server.
when I execute the "post" query, the following error appears:
ERROR
This is my code in the api:
<?php
require 'vendor/autoload.php';
use \Slim\App;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
$app = new Slim\App(['settings' => ['displayErrorDetails' => true]]);
//permite el acceso cors.
$app->options('/{routes:.+}', function ($request, $response, $args) {
return $response;
});
$app->add(function ($req, $res, $next) {
$response = $next($req, $res);
return $response
->withHeader('Access-Control-Allow-Origin', '*')
->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization,token')
->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS')
->withHeader('access-control-expose-headers', 'token,Authorization');
});
require_once "src/routes/routes.php";
$app->run();
ANGULAR: : auth.service.ts
import { GLOBAL } from './global';
import { Router } from '#angular/router';
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
const httpOptions = {
observe: 'response' as 'response',
};
#Injectable({
providedIn: 'root'
})
export class AuthService {
public url: string;
constructor(
public http: HttpClient,
private router: Router) { this.url = GLOBAL.url; }
login(user) {
return this.http.post(this.url + 'login', user, httpOptions);
};
loggedIn() {
//devuelve true si contiene token o falso
return !!localStorage.getItem('token');
}
registrarse(user) {
return this.http.post(this.url + 'usuario', user, httpOptions)
};
}
ANGULAR: : home.component.ts
import { Empresa } from './../../models/empresa';
import { EmpresaService } from './../../services/empresa.service';
import { AuthService } from './../../services/auth.service';
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
empresa: Empresa;
user = {
'id': '',
'email': ''
}
constructor(
private authService: AuthService,
private empresaService: EmpresaService) { }
ngOnInit() {
this.getEmpresa();
this.postLogin();
}
// This request goes well.
getEmpresa() {
let id = 1;
this.empresaService.getEmpresa(id).subscribe(
result => {
console.log(result)
this.empresa = result['data'];
}
)
}
// This request shows me the error
postLogin() {
let user = {
'email': 'adri',
'password': 'adri'
}
this.authService.login(user).subscribe(
result => {
console.log(result.body)
this.user = result.body['data'];
}
)
}
}
Note*:
when I put the API in localhost, the two requests work very well for me: The getEmpresa () and the postLogin ().
but when I put the api on the server, the postLogin () fails.
Angular by default sends in body requests in Content-Type: application / json.
And it is seen that in a more optimized way in production it must be sent in Content-Type: in text / plain.
I have added this code in angular:
const httpOptions = {
observe: 'response' as 'response',
headers: new HttpHeaders({
'Content-Type': 'text/plain',
})
};
#Injectable({
providedIn: 'root'
})
export class AuthService {
public url: string;
constructor(
public http: HttpClient,
private router: Router) { this.url = GLOBAL.url; }
login(user) {
return this.http.post(this.url + 'login', user, httpOptions)
}
and in my REST Slim API I have added the following:
-> json_decode: to decrypt the file that is in JSON format
$app->post('/login', function (Request $request, Response $response) {
$db = conexion();
$json = $request->getBody();
$input = json_decode($json, true);
$sql = "SELECT * FROM usuario WHERE email= :email";
...
...
}
Related
I'm implementing Real-Time Notification in my Laravel project. I'm very close to achieve my goal. What I have done so far is I have saved the notifications into database and now wanted to render the same notification to user using Pusher.
I got response into Pusher but the issue is I' m not able to receive the notification in my console and under the console of another user to make it work like real time.
Currently, notifications are sending to Pusher, saving into database but notification is not showing into console.
App.js
require('./bootstrap');
//getting the ID's of all logged-in users
let userId = document.head.querySelector('meta[name="user-id"]').content;
Echo.private('App.Models.User.' + userId)
.notification((notification) => {
console.log(notification.type);
});
Vue.component('example', require('./components/Example.vue'));
const app = new Vue({
el: '#app',
});
Bootstrap.js
window._ = require('lodash');
window.$ = window.jQuery = require('jquery');
require('bootstrap-sass');
window.Vue = require('vue');
require('vue-resource');
Vue.http.interceptors.push((request, next) => {
request.headers.set('X-CSRF-TOKEN', Laravel.csrfToken);
next();
});
import Echo from "laravel-echo"
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'pusher',
key:'8c1d04bb8d1782b874b1',
cluster: 'ap2',
encrypted: false
});
DatabaseNotification.php
<?php
class DatabaseNotification extends Notification
{
use Queueable;
private $subscription;
public function __construct($letter)
{
$this->subscription = $letter;
}
public function via($notifiable)
{
return ['database','broadcast'];
}
public function toDatabase($notifiable)
{
return [
'letter' => $this->subscription,
];
}
public function toBroadcast($notifiable)
{
return [
'letter' => $this->subscription,
'count' => $notifiable->unreadNotifications->count(),
];
}
}
Response in Pusher
I'm setting up a Vue js/Vuetify website with a PHP Slim Framework API, and tuuopla slim-jwt-auth as a middleware for JWT token authentication.
The unprotected routes are working fine but when I try to send axios requests to the protected routes in the API I only got token not found error.
I dont know if the problem is at Vue js, axios or the API configuration. curl and Postman gives the decoded key as expected when acessing the protected route, only the Vue js website gives this errors.
To run the API I'm using PHP built-in server: `php -S localhost:8000 -t public/
In any case, the localStorage.getItem("token") does exist, as I tried to print them before every request as well in the interceptor.
Here is a test component :
<template>
<v-btn #click="test">Test</v-btn>
<v-btn #click="test2">Test</v-btn>
</template>
<script>
methods: {
test() {
axios
.post("api/user",{},{
headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`
}
}
)
.then(res => console.log(res))
.catch(err => console.log(err));
},
test2() {
var yourConfig = {
headers: {
Authorization: "Bearer " + localStorage.getItem("token")
}
};
axios
.get("test", yourConfig)
.then(res => console.log(res))
.catch(err => console.log(err));
}
},
</script>
axios config(tried with and without the interceptor)
axios.defaults.baseURL = "http://localhost:8000";
axios.interceptors.request.use(
config => {
let token = localStorage.getItem("token");
if (token) {
config.headers["Authorization"] = `Bearer ${token}`;
}
console.log(token)
return config;
},
error => {
return Promise.reject(error);
}
);
Slim index.php(a protected and a unprotected sample routes for my tests)
...
use Slim\Http\Request;
use Slim\Http\Response;
$app->group('/api', function (\Slim\App $app) {
$app->get('/user', function (Request $request, Response $response, array $args) {
return $response->withJson($request->getAttribute('decoded_token_data'));
});
});
$app->get('/test', function (Request $request, Response $response, array $args) {
return $response->withJson(["hi"=>"hello"]);
});
// Run app
$app->run();
middleware.php(tried many configurations)
<?php
// Application middleware
use Slim\Http\Request;
use Slim\Http\Response;
use Monolog\Logger;
use Monolog\Handler\RotatingFileHandler;
$logger = new Logger("slim");
$rotating = new RotatingFileHandler(__DIR__ . "/logs/slim.log", 0, Logger::DEBUG);
$logger->pushHandler($rotating);
$app->add(new \Tuupola\Middleware\JwtAuthentication([
"secure" => false,
"logger" => $logger,
"relaxed" => ["localhost:8080"],
"attribute" => "decoded_token_data",
"secret" => "mykey",
"algorithm" => ["HS256"],
"rules" => [
new \Tuupola\Middleware\JwtAuthentication\RequestPathRule([
// Degenerate access to '/api'
"path" => ["/api"],
// It allows access to 'login' without a token
"passthrough" => [
"/login_admin"
//"/login_admin"
]
])
],
"error" => function ($response, $arguments) {
$data["status"] = "error";
$data["message"] = $arguments["message"];
return $response
->withHeader("Content-Type", "application/json")
->write(json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
}
]));
The errors when tried to access the api/user route:
Chrome console:
OPTIONS http://localhost:8000/api/user net::ERR_ABORTED 401 (Unauthorized)
Access to XMLHttpRequest at 'http://localhost:8000/api/user' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
API Response:
{
"status": "error",
"message": "Token not found."
}
did you try adding
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
to your .htaccess file?
I have a problem with angular, the problem is the following, the method to obtain an http client, does not get any value from an api in php that is listening on the localhost port: 123. The php code would be the follow
<?php
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
//Get todos los usuarios
$app=new \Slim\App;
//Get todos los usuarios
$app->get('/api/clientes', function(Request $request,Response $response){
include "../src/db.php";
$query="select * from users";
$result = mysqli_query($con,$query);
if (!$result) {
die("Query fail");
}else {
$row_cate = mysqli_num_rows($result);
if($row_cate == null){
echo "no existen datos en la dbo";
}
else{
$users=array();
$cont=0;
while ($row = mysqli_fetch_array($result)){
$producto[$cont]=array(
"id" => $row['id'],
"name" => $row['name'],
"email" => $row['email']
);
$cont++;
}
echo json_encode($producto);
}
}
});
and the angular client method is as follows.
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { User } from './user.model';
import { Observable } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class DataService {
constructor(private http:HttpClient) { }
get(){
const url="http://localhost:1234/public/api/clientes";
return new Promise(
resolve=>{
this.http.get(url)
.subscribe(
data=>resolve(data)
)
}
);
}
}
I would appreciate your help.
Your code in get() method is invalid. Here is a better code if you want it to return Promise.
get(): Promise<any> {
const url="http://localhost:1234/public/api/clientes";
return this.http.get(url).toPromise();
}
Also, make sure your server responds with the data you expect
If you are just getting started with Angular, then my advice to you is to learn RxJS and use Observables instead of Promises with Angular.
I already managed to solve the error, the truth was a beginner error, the problem was in the api, I had not put the headers that allowed to perform the procedures "get", "post", etc in php
I have an error in this Component and that error is not caught by command prompt.
Dashboard.component.ts
import { Component, OnInit } from '#angular/core';
import { User } from './user.component';
import { UserService } from './user.service';
#Component({
selector : 'dashboard',
templateUrl : './views/dashboard-component.html',
styleUrls: ['./views/css/dashboard-component.css'],
providers: [UserService]
})
export class DashboardComponent {
users: User[] = [];
constructor(private userservice: UserService){}
ngOnInit() : void{
this.userservice.getusers().then(users => this.users = users.slice(1,5) );
}
}
I can't understand what the problem is because i have defined "users" in the class.
The method is called from this service.
user.service.ts
import { Injectable } from '#angular/core';
import { User } from './user.component';
import { USERS } from './mock-users';
import { Headers, Http } from '#angular/http';
import 'rxjs/add/operator/toPromise';
#Injectable()
export class UserService {
private usersUrl = "http://localhost/user/src/app/userlist.php";
constructor(private http: Http) { }
getusers() : Promise<User[]>{
return this.http.get(this.usersUrl)
.toPromise()
.then(response => response.json().data as User[])
.catch(this.handleError);
}
getuser(id: number): Promise<User> {
const url = '${this.usersUrl}/${id}';
return this.http.get(url)
.toPromise()
.then(response => response.json().data as User)
.catch(this.handleError);
}
private handleError(error : any): Promise<any> {
console.error('an error occured', error);
return Promise.reject(error.message || error);
}
}
The data I am getting is :
[{"id":"1","fname":"Vishwas","lname":"Jadav","email":"vjadav#live.com","dpic":"2017-10-7--09-12-19.jpeg","phone":"7621823474","passw":"illj123","type":"2"}]
You don't have a data property in your response, as we can see you are simply getting an array, so you should return that. So in your service method getusers, instead of...
.then(response => response.json().data as User[])
do:
.then(response => response.json() as User[])
Sidenote, you might have the same problem with your getuser (?) just for future reference if you run into same problem there :)
Try assigning to array and then remove
ngOnInit() : void{
this.userservice.getusers().then(users => this.users = users;
this.users =this.users.slice(1,5);
});
I am brand new in Angular2 framework and I have a problem with http get request. I want to display all registered users on my homepage.
This is my code:
home.service.ts
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import 'rxjs/add/operator/map';
#Injectable()
export class UserService {
constructor (
private http: Http
) {}
getUser() {
return this.http.get(`/app/home/home.php`)
.map((res:Response) => res.json());
}
}
home.component.ts:
// Imports
import { Component, OnInit } from '#angular/core';
import { UserService } from './home.service';
#Component({
templateUrl: './home.component.html'
})
// Component class implementing OnInit
export class HomeComponent{
// Private property for binding
constructor(private userService: UserService) {}
profile = {};
loadUser() {
this.userService.getUser().subscribe(data => this.profile = data);
}
}
home.php
<?php
$connection = new mysqli("127.0.0.1", "root", "", "flatmate");
if($connection->connect_error){
echo $connection->connect_error;
}
/* change character set to utf8 */
if (!$connection->set_charset("utf8")) {
echo $connection->error;
exit();
}
$getUser = 'SELECT * from users';
$result = mysqli_query($connection, $getUser);
$data = array();
while ($row = mysqli_fetch_array($result)) {
$data[] = $row;
}
echo json_encode($data);
home.component.html:
<div>
<button (click)="loadUser()">Load profile</button>
{{ profile | json }}
</div>
In my app.module.ts I added UserService provider. I prepared my code based on this tutorial. When I pass into get method URL from this example, code works properly. But if I change link to my home.php I get the error:
"errors.ts:42 ERROR SyntaxError: Unexpected token < in JSON at position 0"