I tried to make example Ionic application with API with my laravel project. I made Laravel json response api routes. But in my Ionic home page nothing shows up and it reports me this error: Access to XMLHttpRequest at 'http://b.1p1eqpotato.com/ib/?p=1' from origin 'http://localhost:8100' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
zone-evergreen.js:2952 POST http://b.1p1eqpotato.com/ib/?p=1 net::ERR_FAILED
.
And this is console.log
of my laravel posts (3) [{…}, {…}, {…}]0: {id: 1, name: "John Doe", course: "Udemy Academy", created_at: "2020-02-01 13:14:40", updated_at: "2020-02-01 13:14:40"}1: {id: 2, name: "Mike Doe", course: "Software Engineering", created_at: "2020-02-01 13:16:43", updated_at: "2020-02-01 13:16:43"}2: {id: 3, name: "Trevor Doe", course: "Api Ionic Laravel", created_at: "2020-02-01 13:58:24", updated_at: "2020-02-01 13:58:24"}length: 3__proto__: Array(0)
udnefined home.page.ts:24
So this is my Ionic code.
My app.module.ts
:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';
import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { HttpClientModule, HttpClient } from '@angular/common/http';
@NgModule({
declarations: [ AppComponent ],
entryComponents: [],
imports: [ BrowserModule, IonicModule.forRoot(), AppRoutingModule, HttpClientModule ],
providers: [ StatusBar, SplashScreen, { provide: RouteReuseStrategy, useClass: IonicRouteStrategy } ],
bootstrap: [ AppComponent ]
})
export class AppModule {}
My api.service.ts
:
import { Injectable } from '@angular/core';
import { Observable, of, throwError } from 'rxjs';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
import { catchError, tap, map } from 'rxjs/operators';
const httpOptions = {
headers: new HttpHeaders({'Content-type': 'applications/json'})
}
const apiUrl = "http://localhost:8000/api/students";
@Injectable({
providedIn: 'root'
})
export class ApiService {
constructor(private http: HttpClient) { }
private handleError(error: HttpErrorResponse) {
if(error.error instanceof ErrorEvent) {
console.error('An error occurred:', error.error.message);
} else {
console.error(
`Backend returned code ${error.status},` +
`body was: ${error.error}`
);
}
return throwError('Something is wrong, please try again.');
}
private extractData(res: Response) {
let body = res;
return body || { };
}
getDataUser(): Observable<any> {
return this.http.get(apiUrl, httpOptions).pipe(
map(this.extractData),
catchError(this.handleError)
);
}
}
This is home.page.ts
:
import { Component } from '@angular/core';
import { ApiService } from './../api.service';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
datauser: any;
constructor(
public api: ApiService
) {}
ngOnInit(){
this.getDataUser();
}
async getDataUser() {
await this.api.getDataUser()
.subscribe(res => {
console.log(res);
this.datauser = res.results;
console.log(this.datauser);
}, err => {
console.log(err);
});
}
}
And this is my home.page.html
:
<ion-header>
<ion-toolbar>
<ion-title>
Ionic Blank
</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-list>
<ion-item *ngFor="let data of datauser">
{{data.name}}
</ion-item>
</ion-list>
</ion-content>
So it is showing me array
in console but on the Home page view there is nothing. And this error:
Is there any solutions for not showing on the view and this XMLHttpRequest
error? Please help! Thank you
EDITED
This is my ApiController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Student;
class ApiController extends Controller
{
public function getAllStudents() {
// logic to get all students goes here
$students = Student::get()->toJson(JSON_PRETTY_PRINT);
return response($students, 200);
}
public function createStudent(Request $request) {
// logic to create a student record goes here
$student = new Student;
$student->name = $request->name;
$student->course = $request->course;
$student->save();
return response()->json([
"message" => "student record created"
], 201);
}
public function getStudent($id) {
// logic to get a student record goes here
}
public function updateStudent(Request $request, $id) {
// logic to update a student record goes here
}
public function deleteStudent ($id) {
// logic to delete a student record goes here
}
}
This is my api.php
routes:
<?php
use Illuminate\Http\Request;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
Route::get('students', 'ApiController@getAllStudents');
Route::get('students/{id}', 'ApiController@getStudent');
//Route::post('students', 'ApiController@createStudent');
Route::put('students/{id}', 'ApiController@updateStudent');
Route::delete('students/{id}','ApiController@deleteStudent');
And this is my Student.php
model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Student extends Model
{
protected $table = 'students';
protected $fillable = ['name', 'course'];
}
According to Mozilla developer website, CORS happen when a web application tried to send requests to resource that has a different origin (domain, protocol, and port) than its own origin. In my case, http request was made from same host as target resource (localhost) but different port number.
Solution
If you google “how to fix/allow CORS” then you’ll find some websites tells you to add extra headers to your HTTP response by modifying web server configuration. But there is another way you can do in case you have a very little experience with server configuration or you were unable to reach infra guys to ask their help, fix it with Middleware.
What is Middleware?
Middleware is a mechanism for filtering HTTP request coming to your application so you can easily modify HTTP Request and Response in a very convenient way.
Now let’s get to step-by-step:
Create The Class
Create a new file CorsMiddleware.php
inside directory app\Http\Middleware
<?php
/**
* Location: /app/Http/Middleware
*/
namespace App\Http\Middleware;
use Closure;
class CorsMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$headers = [
'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Methods' => 'POST, GET, OPTIONS, PUT, DELETE',
'Access-Control-Allow-Credentials' => 'true',
'Access-Control-Max-Age' => '86400',
'Access-Control-Allow-Headers' => 'Content-Type, Authorization, X-Requested-With'
];
if ($request->isMethod('OPTIONS'))
{
return response()->json('{"method":"OPTIONS"}', 200, $headers);
}
$response = $next($request);
foreach($headers as $key => $value)
{
$response->header($key, $value);
}
return $response;
}
}
This class is used to modify Http Response header, what important here is line number 22 where we tell browser to accept request from any sources (*)
'Access-Control-Allow-Origin' => '*'
Register Middleware
In order to make CorsMiddleware
class known by Laravel next you have to Register it in app\Http\Kernel.php
$app->middleware([
//...
App\Http\Middleware\CorsMiddleware::class
]);
Now you should find that error no more.
It fixed the error Sir ! It is great, but there is still one error. It still don't show me results in my Ionic
home.page.html
view. It is still empty. Why ?Could you ad your brackend controller so i will be able to help you ?
I will add it in a minute sir
I add it Sir. My Laravel backend controller
So my posts from Laravel are showing in
console
of served Ionic App, but it is not displaying on myhome.page.html
view