Angular 6访问REST失败,原因是Access-Control-Allow-Origin [英] Angular 6 accessing REST failing with Access-Control-Allow-Origin

查看:75
本文介绍了Angular 6访问REST失败,原因是Access-Control-Allow-Origin的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我尝试使用'@angular/common/http'中的http: HttpClient将REST源中的数据加载到Angular 6应用程序中.尽管无法使用ng serve --open在浏览器中调用该应用程序.我认为CORS是这里的问题.我想我要么必须使用Access-Control-Allow-Origin或其他方式设置服务器或客户端标头,但是我已经尝试了多种方法,但都没有成功实现此简单的REST调用.所以下面是我编写的代码.

So I am trying to load the data from a REST source into my Angular 6 app using http: HttpClient from '@angular/common/http'. Calling the app in the browser using ng serve --open though doesn't do the job. I assume CORS to be the problem here. I guess I either have to set the server or the client headers with Access-Control-Allow-Origin or something, but I have already tried multiple ways without any success in making this simple REST call work. So what follows below is what I coded.

在浏览器中调用Angular应用会响应以下错误:

Calling the Angular app in the browser responds the following error:

Failed to load http://localhost:8080/mysite-backend/rest/report/single/d83badf3: 
Response to preflight request doesn't pass access control check: 
No 'Access-Control-Allow-Origin' header is present on the requested 
resource. Origin 'http://localhost:4200' is therefore not allowed 
access.

在Chrome浏览器中调用相同的URL(http://localhost:8080/mysite-backend/rest/report/single/d83badf3)可以完美地实现:

Calling the same URL (http://localhost:8080/mysite-backend/rest/report/single/d83badf3) within the Chrome browser works perfectly though:

{"id":"d83badf3","language":"en","categoryId":"a5","title":"Simcity","created":1527723183880,"modified":1527723183880}

在Angular 6中,我使用通过ng generate service tour生成的以下服务类.在其中,我创建了方法getTour(id: string),该方法只不过在URL上调用了REST,然后将检索到的JSON字符串作为Tour对象返回:

Within Angular 6 I use the following service class that I generated with ng generate service tour. Within that I created the method getTour(id: string) which does non more than call REST at the URL and return the retrieved JSON-string as a Tour object:

import { Injectable } from '@angular/core';
import { HttpHeaders, HttpClient } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { Tour } from './tour';
import { catchError, tap } from 'rxjs/operators';

const httpOptions = {
  headers: new HttpHeaders({
    'Content-Type': 'application/json'
  })
};

@Injectable({
  providedIn: 'root'
})
export class TourService {

  // URL to the web api.
  private tourUrl = 'http://localhost:8080/mysite-backend/rest/report';

  constructor(
    private http: HttpClient
  ) { }

  /**
   * 
   * @param id: string GET tour report by id. Will 404 if id not found.
   */
  getTour(id: string): Observable<Tour> {
    httpOptions.headers.append('Access-Control-Allow-Origin', 'http://localhost:8080');
    httpOptions.headers.append('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
    httpOptions.headers.append('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
    httpOptions.headers.append('Access-Control-Allow-Credentials', 'true');

    const url = `${this.tourUrl}/single/${id}`;
    console.log("XXX URL GET " + url)
    return this.http.get<Tour>(url, httpOptions).pipe(
      tap(_ => this.log(`fetched tour id=${id}`)),
      catchError(this.handleError<Tour>(`getHero id=${id}`))
    );
  }

  private handleError<T> (operation = 'operation', result?: T) {
    return (error, any): Observable<T> => {
      console.error(error);
      this.log(`${operation} failed: ${error.message}`);
      return of(result as T);
    };
  }

  private log(message: string) {
    console.log("Log message: " + message);
  }
}

这是Tour对象:

export class Tour {
    id: string;
    language: string;
    categoryId: string;
    created: Date;
    modified: Date;
    title: string;
    content: string;
}

我还将HttpClientModule'@angular/common/http'添加到imports数组和app.module.ts中的providers数组.

I also added HttpClientModule from '@angular/common/http' to the imports array and the providers array within app.module.ts.

RESTful WebService是用Java构建的.在这里,我有一个getReport(@PathParam("reportId") String reportId)方法,该方法获取一个Report对象并在Reponse中将其返回:

The RESTful WebService is built in Java. Here I have the getReport(@PathParam("reportId") String reportId) method, that gets an Report object and returns it within a Reponse:

import java.util.List;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

/**
 * Describes the RESTful access for reports.
 */
@Path("/report")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class ReportResource {
    @Inject
    private Logger logger;

    @GET
    @Path("/single/{reportId}")
    public Response getReport(@PathParam("reportId") String reportId) {
        //return Mock.getReport(reportId);
        return Response.ok() // 200
                       .entity(Mock.getReport(reportId))
                       .header("Access-Control-Allow-Origin", "*")
                       .header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT")
                       .allow("OPTIONS").build();
    }
...
}

我该怎么做才能成功从Angular 6客户端调用Java RESTful WebService?

What must I do to make a successful call from the Angular 6 client to the Java RESTful WebService?

推荐答案

该问题与angular本身无关,但与您使用的Web服务器有关.

The Issue is not related to angular itself, but the the web server you are using.

有角度的http客户端请求在遇到实际请求之前始终具有类型为 options 的预检请求.

The angular http client request always have a preflight request with type options before hitting the actual request.

您可能需要在此行中添加OPTIONS请求方法

you might need to add OPTIONS request method to this line

   .header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT")

这篇关于Angular 6访问REST失败,原因是Access-Control-Allow-Origin的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆