Java Angular 6 使用 Access-Control-Allow-Origin 访问 REST 失败
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/50614896/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Angular 6 accessing REST failing with Access-Control-Allow-Origin
提问by Socrates
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.
因此,我尝试使用http: HttpClient
from将来自 REST 源的数据加载到我的 Angular 6 应用程序中'@angular/common/http'
。使用ng serve --open
虽然在浏览器中调用应用程序并不能完成这项工作。我认为 CORS 是这里的问题。我想我要么必须设置服务器或客户端标头Access-Control-Allow-Origin
或其他东西,但我已经尝试了多种方法,但没有成功使这个简单的 REST 调用工作。所以下面是我编码的内容。
Calling the Angular app in the browser responds the following error:
在浏览器中调用 Angular 应用会响应以下错误:
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.
Calling the same URL (http://localhost:8080/mysite-backend/rest/report/single/d83badf3
) within the Chrome browser works perfectly though:
http://localhost:8080/mysite-backend/rest/report/single/d83badf3
不过,在 Chrome 浏览器中调用相同的 URL ( ) 效果很好:
{"id":"d83badf3","language":"en","categoryId":"a5","title":"Simcity","created":1527723183880,"modified":1527723183880}
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:
在 Angular 6 中,我使用了以下由ng generate service tour
. 在其中,我创建了一个方法getTour(id: string)
,它只在 URL 上调用 REST,并将检索到的 JSON 字符串作为 Tour 对象返回:
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);
}
}
This is the Tour
object:
这是Tour
对象:
export class Tour {
id: string;
language: string;
categoryId: string;
created: Date;
modified: Date;
title: string;
content: string;
}
I also added HttpClientModule
from '@angular/common/http'
to the imports
array and the providers
array within app.module.ts
.
我还添加HttpClientModule
从'@angular/common/http'
所述imports
阵列和providers
内阵列app.module.ts
。
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
:
RESTful WebService 是用 Java 构建的。这里我有一个getReport(@PathParam("reportId") String reportId)
方法,它获取一个Report
对象并在 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();
}
...
}
What must I do to make a successful call from the Angular 6 client to the Java RESTful WebService?
我必须做什么才能从 Angular 6 客户端成功调用 Java RESTful WebService?
采纳答案by Ihab Salem
The Issue is not related to angular itself, but the the web server you are using.
该问题与 angular 本身无关,而是与您使用的 Web 服务器有关。
The angular http client request always have a preflight request with type optionsbefore hitting the actual request.
在点击实际请求之前,angular http 客户端请求总是有一个带有类型选项的预检请求。
you might need to add OPTIONS request method to this line
您可能需要在此行中添加 OPTIONS 请求方法
.header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT")
回答by Kmaj
The following steps helped me to resolve it:
以下步骤帮助我解决了这个问题:
1- create proxy.conf.json
file under your project root instead of src folder
1-proxy.conf.json
在您的项目根目录下创建文件而不是 src 文件夹
3- Add code as below in proxy.conf.json
file.
3- 在proxy.conf.json
文件中添加如下代码。
{
"/api": {
"target": "http://localhost:3000",
"secure": false
}
}
4- add this exactly in package.json
under scripts "start": ng serve --proxy-config proxy.conf.json
4-package.json
在脚本下准确添加"start": ng serve --proxy-config proxy.conf.json
5- do npm start
instead of ng serve
5-做npm start
而不是ng serve
回答by Pruthviraj
I solved CORS problem using proxy.
我使用代理解决了 CORS 问题。
- Create a file proxy.conf.json at the same level as package.json.
- add following content
- 创建与 package.json 相同级别的文件 proxy.conf.json。
- 添加以下内容
{
"/api/*": {
"target": "http://external-domain-you-wanted-to-access",
"secure": false,
"changeOrigin": true
}
}
- Run the command ng serve --proxy-config proxy.conf.json
- 运行命令ng serve --proxy-config proxy.conf.json
回答by Ambar Dudhane
I almost spent day with resolving the problem. First I thought issue is from angular side but it seems that issue was from server side. You need to add @CrossOrigin annotation above the get method.
我几乎花了一天时间来解决问题。首先我认为问题来自角度方面,但似乎问题来自服务器端。您需要在 get 方法上方添加 @CrossOrigin 注释。
@GET
@CrossOrigin(origins = "http://localhost:4200")
@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();
}
回答by Agnel Amodia
I wasted almost a day in figuring out at client side angular application but the problem actually was at server side nodejs application to allow CORS.
我在客户端角度应用程序上浪费了将近一天的时间,但问题实际上是在服务器端 nodejs 应用程序上允许 CORS。
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});