AngularJS는 출처 간 자원에 대한 OPTIONS HTTP 요청을 수행합니다.
템플릿 파일을 제공하는 자산 호스트가 다른 도메인에 있으므로 각도가 수행하는 XHR 요청이 도메인 간이어야하는 교차 출처 리소스와 통신하도록 AngularJS를 설정하려고합니다. HTTP 요청 이이 작업을 수행 할 수 있도록 적절한 CORS 헤더를 서버에 추가했지만 작동하지 않는 것 같습니다. 문제는 브라우저 (크롬)에서 HTTP 요청을 검사 할 때 자산 파일로 전송 된 요청이 OPTIONS 요청 (GET 요청이어야 함)이라는 것입니다.
이것이 AngularJS의 버그인지 또는 무언가를 구성 해야하는지 확실하지 않습니다. 내가 이해 한 바에 따르면 XHR 래퍼는 OPTIONS HTTP 요청을 할 수 없으므로 브라우저가 GET 요청을 수행하기 전에 먼저 자산을 다운로드 할 수 있는지 여부를 파악하려고하는 것처럼 보입니다. 이 경우 자산 호스트로 CORS 헤더 (Access-Control-Allow-Origin : http://asset.host .. )를 설정해야합니까?
OPTIONS 요청은 결코 AngularJS 버그가 아니며, 이는 Cross-Origin Resource Sharing 표준이 브라우저의 동작을 지시하는 방식입니다. https://developer.mozilla.org/en-US/docs/HTTP_access_control 문서를 참조하십시오. 여기서 "개요"섹션에 다음과 같이 나와 있습니다.
Cross-Origin Resource Sharing 표준은 서버가 웹 브라우저를 사용하여 해당 정보를 읽을 수있는 원본 세트를 설명 할 수있는 새로운 HTTP 헤더를 추가하여 작동합니다. 또한 사용자 데이터에 부작용을 일으킬 수있는 HTTP 요청 방법 (특히 GET 이외의 HTTP 방법 또는 특정 MIME 유형의 POST 사용) 이 사양은 브라우저가 HTTP OPTIONS 요청 헤더를 사용하여 서버에서 지원되는 메소드를 요청한 다음 서버에서 "승인"하면 실제 HTTP 요청 메소드를 사용하여 실제 요청을 전송하도록 브라우저가 요청을 "프리 플라이트"하도록 규정합니다. 서버는 또한 "신임 정보"(쿠키 및 HTTP 인증 데이터 포함)를 요청과 함께 보내야하는지 여부를 클라이언트에 알릴 수 있습니다.
서버 자체와 지원하려는 HTTP 동사에 따라 설정이 달라 지므로 모든 WWW 서버에서 작동하는 일반적인 솔루션을 제공하는 것은 매우 어렵습니다. 서버에서 보내야하는 정확한 헤더에 대한 자세한 내용 이 포함 된이 훌륭한 기사 ( http://www.html5rocks.com/en/tutorials/cors/ ) 를 극복 하시기 바랍니다.
Angular 1.2.0rc1 +의 경우 resourceUrlWhitelist를 추가해야합니다.
1.2 : 릴리스 버전에서는 escapeForRegexp 함수를 추가하여 더 이상 문자열을 이스케이프 할 필요가 없습니다. 당신은 URL을 직접 추가 할 수 있습니다
'http://sub*.assets.example.com/**'
하위 폴더에 **를 추가해야합니다. 1.2의 작동하는 jsbin은 다음과 같습니다. http://jsbin.com/olavok/145/edit
1.2.0rc : 여전히 rc 버전 인 경우 Angular 1.2.0rc1 솔루션은 다음과 같습니다.
.config(['$sceDelegateProvider', function($sceDelegateProvider) {
$sceDelegateProvider.resourceUrlWhitelist(['self', /^https?:\/\/(cdn\.)?yourdomain.com/]);
}])
다음은 1.2.0rc1에서 작동하는 jsbin 예제입니다. http://jsbin.com/olavok/144/edit
1.2 이전 : 이전 버전 ( http://better-inter.net/enabling-cors-in-angular-js/ 참조 )의 경우 구성에 다음 두 줄을 추가해야합니다.
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
1.2 이전 버전에서 작동하는 jsbin 예제는 다음과 같습니다. http://jsbin.com/olavok/11/edit
참고 : 최신 버전의 Angular에서는 작동하지 않습니다.
기발한:
OPTIONS 요청을 무시할 수도 있습니다 (Chrome에서만 테스트 됨).
app.config(['$httpProvider', function ($httpProvider) {
//Reset headers to avoid OPTIONS request (aka preflight)
$httpProvider.defaults.headers.common = {};
$httpProvider.defaults.headers.post = {};
$httpProvider.defaults.headers.put = {};
$httpProvider.defaults.headers.patch = {};
}]);
서비스는 OPTIONS
다음과 같은 헤더 로 요청에 응답해야합니다 .
Access-Control-Allow-Origin: [the same origin from the request]
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: [the same ACCESS-CONTROL-REQUEST-HEADERS from request]
다음은 좋은 문서입니다. http://www.html5rocks.com/en/tutorials/cors/#toc-adding-cors-support-to-the-server
같은 문서가 말합니다
위에서 설명한 간단한 요청과 달리, "미리 비행 된"요청은 먼저 실제 요청이 안전하게 전송되는지 확인하기 위해 다른 도메인의 리소스에 HTTP OPTIONS 요청 헤더를 보냅니다. 사이트 간 요청은 사용자 데이터에 영향을 줄 수 있으므로 이와 같이 프리 플라이트됩니다. 특히 다음과 같은 경우 요청이 프리 플라이트됩니다.
GET 또는 POST 이외의 메소드를 사용합니다. 또한 POST를 사용하여 application / x-www-form-urlencoded, multipart / form-data 또는 text / plain 이외의 Content-Type으로 요청 데이터를 보내는 경우 (예 : POST 요청이 서버에 XML 페이로드를 보내는 경우) application / xml 또는 text / xml을 사용하면 요청이 프리 플라이트됩니다.
요청에 사용자 정의 헤더를 설정합니다 (예 : 요청에 X-PINGOTHER와 같은 헤더가 사용됨)
원래 요청이 사용자 지정 헤더없이 가져 오기 인 경우 브라우저는 지금 요청하는 옵션을 요청하지 않아야합니다. 문제는 옵션 요청을 강제로 수행하는 헤더 X-Requested-With를 생성한다는 것입니다. 이 헤더를 제거하는 방법 은 https://github.com/angular/angular.js/pull/1454 를 참조 하십시오 .
이것은 내 문제를 해결했다.
$http.defaults.headers.post["Content-Type"] = "text/plain";
nodeJS 서버를 사용하는 경우이 라이브러리를 사용할 수 있습니다. https://github.com/expressjs/cors
var express = require('express')
, cors = require('cors')
, app = express();
app.use(cors());
그리고 당신이 할 수있는 후 npm update
.
ASP.NET 에서이 문제를 해결 한 방법은 다음과 같습니다.
먼저 너겟 패키지 Microsoft.AspNet.WebApi.Cors를 추가해야합니다.
그런 다음 App_Start \ WebApiConfig.cs 파일을 수정하십시오.
public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.EnableCors(); ... } }
컨트롤러 클래스에이 속성을 추가하십시오.
[EnableCors(origins: "*", headers: "*", methods: "*")] public class MyController : ApiController { [AcceptVerbs("POST")] public IHttpActionResult Post([FromBody]YourDataType data) { ... return Ok(result); } }
이런 식으로 json을 액션에 보낼 수있었습니다.
$http({ method: 'POST', data: JSON.stringify(data), url: 'actionurl', headers: { 'Content-Type': 'application/json; charset=UTF-8' } }).then(...)
참조 : ASP.NET Web API 2에서 교차 출처 요청 활성화
어떻게 든 변경하여 수정했습니다.
<add name="Access-Control-Allow-Headers"
value="Origin, X-Requested-With, Content-Type, Accept, Authorization"
/>
에
<add name="Access-Control-Allow-Headers"
value="Origin, Content-Type, Accept, Authorization"
/>
pkozlowski의 의견에 완벽하게 설명되어 있습니다. AngularJS 1.2.6 및 ASP.NET Web Api로 작업 솔루션을 사용했지만 AngularJS를 1.3.3으로 업그레이드하면 요청이 실패했습니다.
Web Api 서버를위한 솔루션은 구성 방법 시작시 OPTIONS 요청 처리를 추가하는 것이 었습니다 ( 이 블로그 게시물에서 자세한 정보 참조 ).
app.Use(async (context, next) => { IOwinRequest req = context.Request; IOwinResponse res = context.Response; if (req.Path.StartsWithSegments(new PathString("/Token"))) { var origin = req.Headers.Get("Origin"); if (!string.IsNullOrEmpty(origin)) { res.Headers.Set("Access-Control-Allow-Origin", origin); } if (req.Method == "OPTIONS") { res.StatusCode = 200; res.Headers.AppendCommaSeparatedValues("Access-Control-Allow-Methods", "GET", "POST"); res.Headers.AppendCommaSeparatedValues("Access-Control-Allow-Headers", "authorization", "content-type"); return; } } await next(); });
REST API에 Jersey를 사용하는 경우 다음과 같이 할 수 있습니다
웹 서비스 구현을 변경할 필요가 없습니다.
Jersey 2.x에 대해 설명하겠습니다
1) 먼저 아래와 같이 ResponseFilter를 추가하십시오.
import java.io.IOException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
public class CorsResponseFilter implements ContainerResponseFilter {
@Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
throws IOException {
responseContext.getHeaders().add("Access-Control-Allow-Origin","*");
responseContext.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
}
}
2) 그런 다음 web.xml에서 저지 서블릿 선언에 아래를 추가하십시오.
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>YOUR PACKAGE.CorsResponseFilter</param-value>
</init-param>
이 문제를 해결하려고 포기했습니다.
내 IIS web.config에 관련 " Access-Control-Allow-Methods
"이 포함되어 있는데, Angular 코드에 구성 설정을 추가하는 실험을했지만 Chrome에서 도메인 간 JSON 웹 서비스를 호출하도록 몇 시간 동안 작업 한 후 비참하게 포기했습니다.
결국, 나는이 ASP.Net 처리기 웹 페이지 바보있어 추가 그건 내 JSON 웹 서비스를 호출하고 결과를 반환 할 수 있습니다. 2 분 안에 가동되었습니다.
내가 사용한 코드는 다음과 같습니다.
public class LoadJSONData : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
string URL = "......";
using (var client = new HttpClient())
{
// New code:
client.BaseAddress = new Uri(URL);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("Authorization", "Basic AUTHORIZATION_STRING");
HttpResponseMessage response = client.GetAsync(URL).Result;
if (response.IsSuccessStatusCode)
{
var content = response.Content.ReadAsStringAsync().Result;
context.Response.Write("Success: " + content);
}
else
{
context.Response.Write(response.StatusCode + " : Message - " + response.ReasonPhrase);
}
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
그리고 내 Angular 컨트롤러에서 ...
$http.get("/Handlers/LoadJSONData.ashx")
.success(function (data) {
....
});
나는 이것을하는 더 간단하고 일반적인 방법이 있다고 확신하지만 인생은 너무 짧습니다 ...
이것은 나를 위해 일했고 지금은 정상적인 작업을 계속할 수 있습니다!
IIS MVC 5 / Angular CLI의 경우 (예, API가있는 Angular JS 문제가 있음을 잘 알고 있습니다.) 다음을 수행했습니다.
<system.webServer>
노드 아래의 web.config
<staticContent>
<remove fileExtension=".woff2" />
<mimeMap fileExtension=".woff2" mimeType="font/woff2" />
</staticContent>
<httpProtocol>
<customHeaders>
<clear />
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type, atv2" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS"/>
</customHeaders>
</httpProtocol>
global.asax.cs
protected void Application_BeginRequest() {
if (Request.Headers.AllKeys.Contains("Origin", StringComparer.OrdinalIgnoreCase) && Request.HttpMethod == "OPTIONS") {
Response.Flush();
Response.End();
}
}
그렇게하면 MVC와 WebAPI 모두에 대한 문제를 해결해야합니다. 그런 다음 Angular CLI 프로젝트에서 관련 헤더 정보에 자동으로 추가되는 HttpInterceptor를 작성했습니다. 이것이 비슷한 상황에서 누군가를 돕기를 바랍니다.
파티에 조금 늦었 어
Angular 7 (또는 5/6/7) 및 PHP를 API로 사용하고 있는데도 여전히이 오류가 발생하면 다음 헤더 옵션을 엔드 포인트 (PHP API)에 추가하십시오.
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: PUT, GET, POST, PUT, OPTIONS, DELETE, PATCH");
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization");
참고 : 필요한 것은 Access-Control-Allow-Methods
입니다. 하지만, 여기에 다른 두 붙여 넣기하고 Access-Control-Allow-Origin
그리고 Access-Control-Allow-Headers
제대로 제대로 API 이야기를 위해 각도 App에서 설정하는 모든 이들의 필요합니다 간단하기 때문에.
이것이 누군가를 돕기를 바랍니다.
건배.
'IT' 카테고리의 다른 글
ENABLE_BITCODE는 xcode 7에서 무엇을합니까? (0) | 2020.03.31 |
---|---|
중복 키를 HashMap에 넣으면 어떻게됩니까? (0) | 2020.03.31 |
DOM 요소를 jQuery 요소로 변환하려면 어떻게해야합니까? (0) | 2020.03.31 |
find 명령으로 정규식을 사용하는 방법은 무엇입니까? (0) | 2020.03.31 |
LINQ : 전혀 그렇지 않다 (0) | 2020.03.31 |