How to add custom headers to request with cljs-http - http

I am using cljs-http and I am not able add custom headers into http request. Adding code snippet with request creation:
arg {:basic-auth auth
:headers {
"Access-Control-Allow-Origin" " *"
"Access-Control-Allow-Headers" "Origin, X-Custom-Header, Content-Type, Accept"
"X-Custom-Header" "Custom header"}
resp (csp/<! (cljs-http/get url arg))
Output in chrome console:
XMLHttpRequest cannot load url. Request header field X-Custom-Header is not allowed by Access-Control-Allow-Headers.
Could you please suggest me how to do it ?

The problem was related not to clojurescript, but to server side.
The CORS headers were not configured.
While handling requests, server should attach Access-Control-Allow-Origin, Access-Control-Request-Method headers to response that's permit performing requests for frontend (cljs).

Related

Get CORS request works but Put CORS request fails in AWS Lambda proxy integration (.net6)

I am building a collection of lambdas with proxy integration, using AWS Serverless (SAM).
I am trying my Lambdas from a frontend I have in Blazor WASM. When a GET request is issued, then I get my results on my browser without CORS issues.
But I cannot issue a PUT request without getting the dreaded:
Access to fetch at 'https://myapi.execute-api.eu-central-1.amazonaws.com/Prod/updatevictual?userId=georanto#gmail.com&victualId=da1b2daa-3a73-425e-812e-e2f164f54507' from origin 'https://localhost:7260' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
If I create a dedicated OPTIONS Lambda for the PUT related end-point (as suggested here) then it works. I cannot have an OPTIONS Lambda because I intend to add authentication and the OPTIONS lambda does not work with it.
According to this it should be enough to send the headers as a response. And in the case of GET it is!
To fill in my response headers(adjusting for .net6), I set my cors by attaching the headers at the returned request thus:
private static APIGatewayProxyResponse AllowCors(this APIGatewayProxyResponse response)
{
response.Headers ??= new Dictionary<string, string>();
response.Headers.Add("Access-Control-Allow-Headers",
"Content-Type, Authorization, X-Amz-Date, X-Api-Key, X-Amz-Security-Token");
response.Headers.Add("Access-Control-Allow-Methods", "*");
response.Headers.Add("Access-Control-Allow-Origin", "*");
response.Headers.Add("Access-Control-Allow-Credentials", "false");
return response;
}
I am also logging my responses in Cloudwatch and the put response after the postman request is thus:
2022-05-12T06:08:30.297Z ecffb8ac-0cd9-4626-be96-6260e7a76d47 info Responding with:[{
"statusCode": 201,
"headers": {
"Access-Control-Allow-Headers": "Content-Type, Authorization, X-Amz-Date, X-Api-Key, X-Amz-Security-Token",
"Access-Control-Allow-Methods": "*",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Credentials": "false"
},
"multiValueHeaders": null,
"body": null,
"isBase64Encoded": false}]
When I issue the request in Postman I see in the response's headers that the CORS headers are set the way they were supposed to:
So I don't think that this is a code issue.
I have also tried to put all the methods (i.e. response.Headers.Add("Access-Control-Allow-Methods", "OPTIONS, DELETE, GET, HEAD, PATCH, POST, PUT") but also didn't work.
Any other ideas what could that be?
I "think" I had the same issue but I'm not familiar with .net... in your cloudfront distribution configuration, be sure to have a caching behavior that allows for put/patch/etc. and configure in that behavior a cache policy that depends on your headers

AWS - has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource

I used visual studio net 2.1 and a local sql database for my site on AWS. The first page comes up but when I try to put in a comment and the code routes to another page on my site I get this console error and the page is not routed to in the browser:
Access to XMLHttpRequest at 'https...' from origin 'https://www.....dev' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
This is the startup.cs file
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
);
});
app.UseCors("CorsPolicy");
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
For some CORS requests, the browser sends an additional OPTIONS request before making the actual request. This request is called a preflight request. The browser can skip the preflight request if all the following conditions are true:
The request method is GET, HEAD, or POST.
The app doesn't set request headers other than Accept, Accept-Language, Content-
Language, Content-Type, or Last-Event-ID.
The Content-Type header, if set, has one of the following values:
application/x-www-form-urlencoded
multipart/form-data
text/plain
AllowAnyOrigin affects preflight requests and the Access-Control-Allow-Origin header.
The preflight request uses the HTTP OPTIONS method. It may include the following headers:
Access-Control-Request-Method: The HTTP method that will be used for the actual request.
Access-Control-Request-Headers: A list of request headers that the app sets on the actual request.
Access-Control-Allow-Methods
Try allowing specific origins, methods and headers.
For more information can check the below link:
https://learn.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-3.1#preflight-requests
THe answer is to enable the api-gateway in AWS
In API Gateway Console click the Actions dropdown and select Deploy API.
This eliminated the CORS issue.

HERE-maps CORS problems with Autocomplete

I want to use HERE maps autocomplete in my project.
But when a i send request like the one in documentation
this.axios.get('http://autocomplete.geocoder.api.here.com/6.2/suggest.json
?app_id={YOUR_APP_ID}
&app_code={YOUR_APP_CODE}
&query=Pariser+1+Berl
&beginHighlight=<b>
&endHighlight=</b>'
)
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error)
})
i get an error
OPTIONS http://autocomplete.geocoder.api.here.com/6.2/suggest.json?{...} 405
Access to XMLHttpRequest at 'http://autocomplete.geocoder.api.here.com/6.2/suggest.json?{...}' 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.
In Chrome developer console in network panel i check this
Provisional headers are shown
Access-Control-Request-Headers: x-auth-token, content-type
Access-Control-Request-Method: GET
I set content-type in request headers to application/json and Provisional headers changed
to Access-Control-Request-Headers: x-auth-token
Access-Control-Request-Method: GET
So if i understand right, i should set x-auth-token header. But where can i take this token?
Or may be this problem has another reason?
There's nothing about such problems in documentaion.
The problem was simple and a bit stupid.
When user authenticated in my app I added default header to axios
axios.defaults.headers.common['X-Auth-Token'] = token
so this header was sended to all requests.
But HERE-map API doesn't want this header in requests and this was the cause of the problem.
The solution was to remove this header from requests to HERE-map API.
For those who have defined by default the header :
'Content-Type': 'application/json'
You must deactivate it, there should not be any HttpHeaders on the call request to Here API services.
temporary install Allow-Control-Allow-Origin google chrome plugin .. installed then you can show top right side click on that and switch the button then refresh then again call your api and get the response.

Vue-Request not sending Authorization Header

I'm using VueJS with vue-request for http requests. I'm trying to subscribe an user to a Mailchimp list but Mailchimp uses BasicAuth, so I'm doing as such:
scope.$http.post('https://us15.api.mailchimp.com/3.0/lists/listid/members',
{...mydata...}, {headers: {Authorization: 'Basic myencodedAPIkey'}})
But I get an error from the API: 401 Unauthorized - Your request did not include an API key.
So I check the Network log on Chrome and the Authorization is on my headers like this: **Access-Control-Request-Headers: authorization** but it should be like **Authorization: myencodedAPIkey**
On the Console the error appears as:
XMLHttpRequest cannot load
https://us15.api.mailchimp.com/3.0/lists/listid/members. Response
to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://127.0.0.1:8000' is therefore not allowed
access. The response had HTTP status code 401.
When I use Postman it works just fine as the header is correctly sent.
This problem seems to have been solved here with setting the header on every request
https://laracasts.com/discuss/channels/vue/how-to-solve-the-allow-control-allow-cross-in-the-vuejs-header-request-setting?page=2
and here through setting it once
Vue-Request not sending Authorization Header
You are getting CORS error, when you are trying to request from one host to another, and the 'another' part does not allow it to happen. To prevent this error you can use webpack proxy configuration, so this way you do not have cross origin request, but I don't know how you will deal with this in production environment if your api does not allow cross origin requests.
In a project I'm working on, our devServer configuration is as follow
proxy: {
'/api': {
target: 'http://localhost:8080/'
}
},
with this, any request happening on /api/any/url will be redirect to localhost:8080/api/any/url

Avoiding preflight OPTIONS requests with CORS

I am building an Angular app that interacts with an API built with ASP.NET Web API 2. I am using Basic Authentication by sending an Authorization header with each request that requires authentication:
Angular snippet:
$http.defaults.headers.common['Authorization'] = authHeader;
Request:
Accept:application/json, text/javascript
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Max-Age:1728000
Authorization:Basic [base64 encoded credential couplet here]
Connection:keep-alive
DNT:1
Host: blah.com
Origin:http://localhost:9000
Referer:http://localhost:9000/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/53
This all works OKAY, but a preflight OPTIONS request is sent with every GET or POST request. This is majorly impacting the perceived speed of the application. I have done lots of reading on CORS "Simple Requests" and it seems that in order to avoid the dreaded preflight OPTIONS request is to avoid adding any custom headers in my requests. I've tried lots of other stuff like sending a Content-Type of text/plain, but it seems that the Authorization header is the thing that is violating the CORS "Simple request" requirement.
So it seems that I may have to move the API over to use token based authentication/authorization. In order to avoid preflight requests, it seems that I will need to place the token in the query string. This is okay as it is only a small internal web app which will only be accessed by a couple of users anyway. I intend to implement caching on controller responses. As each request to an controller action will have a different token in the querystring based on the currently authenticated user, will this render cacheing useless?
So:
How do I avoid preflight requests (using custom Authorization headers if at all possible)
If 1.) is not possible, and I move to token based auth, will I be unable to cache API responses for controller actions
What are the most widely used methods to avoid preflight requests but also to auth users securely?
n.b I know there are a couple of other threads on SO and elsewhere on the web regarding this, but none of them tend to provide a definitive answer on whether it is possible to avoid preflight requests for GETs and POSTs when using custom HTTP authorization headers.
I think this post (How to apply CORS preflight cache to an entire domain) pretty much says it all - there is not much you can do about this
The one simple solution is to add a reverse proxy to the proxy/webserver serving your angular app (e.g. nginx) to route your RESTful calls via the same domain, e.g. appdomain.com/api --> apidomain.com.
Another solution that seems to be working OK for me. Instead of setting up a proxy and needing to route to the same domain, it is possible to return the preflight request directly from nginx and therefore reducing the time required by the preflight request down to just a couple of milliseconds.
Here is a simple snippet that can be used with nginx.
location / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
}
Once the preflight request is successful, it is then possible to simple add "Access-Control-Allow-Origin" and other necessary stuff to the 'GET','POST' requests, etc...

Resources