Azure functions & HTTP OPTIONS request - azure

I want an existing application (which I do not control) to send information to an Azure function.
The application first sends a HTTP OPTIONS request, and will then regularly send HTTP POST messages.
The problem I have is that the application expects a header "Allow : POST,OPTIONS" in the response from the Azure function on the OPTIONS request. If the header is not present, it will not continue (instead, it throws an error : 'POST is not allowed')
When trying to set the header in Azure functions, I get the following error message
System.Net.Http: Misused header name. Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects.
I did enable CORS for all locations, and allowed all methods in the configuration.
module.exports = function (context, req)
{
//context.log('JavaScript HTTP trigger function processed a request.');
if (req.method == "OPTIONS")
{
context.res =
{
body: "",
headers:
{
//"Access-Control-Allow-Methods" : "POST,OPTIONS",
"allow" : "POST,OPTIONS"
},
status: 200,
};
}
context.done();
}
The specification say that the Allow header should be set for a 405 response. If the header is empty, nothing is allowed. However, there is no logic defined for when the header is not present at all.
Is there a method through which I can send this header in response to the HTTP OPTIONS ?

The error is expected. Function runtime is based on C#, when the response tries to add the Allow header, underlying C# code checks its name. It's by design that Allow is a read-only header in HttpContentHeaders hence we can't add it in HttpResponseHeaders.
Here are two workarounds for you to refer.
Use a custom header name like Allow-Method.
Create a new Function app, it uses Function runtime 2.0 by default, where we can set Allow header.

If you are editing this through the portal, navigate to the integrate section of the function and select POST and OPTIONS methods.

Have you tried adding the allowed methods to the function.json files as noted in the documentation?
Example below:
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"post",
"options"
]

Solved it through putting an APIM in front of teh logic app. This APIM just returns a 200 in case of the OPTIONS request, and calls the logic app for the subsequent HTTP post requests

Related

AWS API Gateway returns access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response

This may seem like it's been asked a million times but I've tried adding to both my frontend (React) and backend (Lambda with Node.js):
Access-Control-Allow-Headers
Access-Control-Request-Headers
Access-Control-Allow-Methods: 'GET,PUT,POST,DELETE,PATCH,OPTIONS'
But I still get this error:
Access to XMLHttpRequest at 'https://<API-INVOKE-URL>/prod/notes' from origin 'http://localhost:3000' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response.
Here's my Lambda code to handle response:
function buildOutput(statusCode, data) {
let _response = {
statusCode: statusCode,
headers: {
"Access-Control-Allow-Origin": "*"
},
body: JSON.stringify(data)
};
return _response;
};
Here's my React code to send the POST request:
createNote(note) {
return API.post("notes", "/notes", {
headers: {
"Authorization": this.state.token,
"Access-Control-Allow-Origin": "*"
},
body: {
userid: this.state.username,
noteid: 'new',
content: 'from frontend'
}
});
I've tested my Lambda function from the console and it works (able to do CRUD to DynamoDB).
I've turned on CORS for my API Gateway resources and deployed the API.
I've tried using PostMan with:
Headers:Content/Type: application/json
Authorization: <MY_TOKEN>
*With and without* Access-Control-Allow-Origin: *
and it works: the request is sent successfully from PostMan to API Gateway results in a new item in my DynamoDB.
Actually adding some data in header converts POST request to OPTIONS.
So that, it will fire to requests:
1) with OPTIONS method
2) After getting a successfull response for OPTIONS request, the actual API call will occur.
To handle CORS you should use this in the backend.
Just to throw some light to the problem. Some browsers will do a "preflight" check to your endpoint. That means that will invoke your endpoint with OPTIONS method before making the POST method call you expect. In AWS, go to API Gateway and create a new resource , check the option to Create Options, that will create the default response headers that you need to add to your endpoint.
CORS requires a direct connection between the client and server. Your browser may be blocking the connection for security reasons.
HTTP versus HTTPS
I'd also try enabling downloads on your browser.
I believe you should also add the bearer to your token in the authorization header like:
'Bearer TOKEN_VALUE'
Thank you, guys. I've upvoted your answers/suggestions. I'm sure they're helpful in most cases. I've figured out why I had that error.
My bad: I have both resources like this:
/notes/ (method: any)
/notes/{noteid} (method: any)
and the Invoke URL is literally <path>/notes/{noteid} (with the {} included in the string) in AWS API Gateway. I was assuming it'd be something like /notes/:noteid
So the frontend code should be like this:
return API.post("notes", "/notes/{noteid}", {...}

How to avoid headers passed back to API Gateway from Lambda via Serverless framework being remapped?

I'm hitting an issue when I try to respond in a Serverless Lambda function with the WWW-Authenticate challenge header.
I am setting in my response
{
statusCode: 401,
headers: {
'WWW-Authenticate': 'Basic realm="My realm"',
},
body: "",
}
The function runs successfully but in the response I don't have a WWW-Authenticate header; instead, I have an x-amzn-Remapped-WWW-Authenticate header.
How can I have this header passed through verbatim?
I read the docs about passing custom response headers, but it seems that these need to be set in serverless.yml. Since these response headers need to be dynamic based on the request headers I don't think that will help me.
The function is the default lambda-proxy type.
By default The Serverless Framework uses the Lambda Proxy Integration method. This does lots of the heavy lifting for you, but also gets in the way.
If you want a more transparent experience you need to use Lambda Integration, and handle the response yourself. Though you'll need to get more hands on, including CORS response headers.
integration: lambda
You can read more about the two methods here: https://serverless.com/framework/docs/providers/aws/events/apigateway/#lambda-integration

Are there any websites that allow you to perform GET requests using there API?

I'm working on a project where I need to perform a GET request to a domain. It won't work purely in Javascript because the site is cross-origin. Is there a service that when called can return the contents of a page?
this one :) specifically this endpoint over here
/get Returns GET data.
it will reply every time you call it with a response like this
{
"args": {},
"headers": {
// all the headers will be here
},
"origin": "<YOUR IP WILL BE HERE>",
"url": "https://httpbin.org/get"
}
JSON format that you can consume and view to your client/end

Changing User-Agent in XMLHttpRequest from a Chrome extension

I'm trying to send a HTTP request from a Extension in which I need to change the User-Agent.
My code looks like this:
function getXMLHttpRequest(method, url, extraHeaders) {
var xhr = new XMLHttpRequest();
xhr.open(method, url, true)
for (var headerKey in extraHeaders) {
xhr.setRequestHeader(headerKey, extraHeaders[headerKey]);
}
return xhr;
}
//....
getXMLHttpRequest("POST", "....", { "User-Agent": "Blahblahblah" })
Then, I get an error "Refused to set unsafe header: UserAgent"
I need to change that because my Backend needs to have an special User-Agent, is it possible to do that from an extension?
I tried webRequest API, to change the header before sending the request, but it says it does not work with XMLHttpRequest made from extensions in order to prevent locking.
You can easily change the User-Agent header with the webRequest API.
For sample code, see Associate a custom user agent to a specific Google Chrome page/tab.
Take the code from that answer, and change "main_frame", "sub_frame" to "xmlhttprequest" to modify network requests initiated via XMLHttpRequest.
Obviously, to prevent deadlocks, this method does not work with synchronous requests ( i.e. when the third parameter of xhr.open is set to false).

WCF Web API RESTful is not allowed by Access-Control-Allow-Origin

Seems like I have a cross domain access problem.
I've seen some solutions that are indicating to add "Access-Control-Allow-Origin: *", but I don't know where I can do this.
Do I need to create some handler?
I'm using WCF Web API.
Error: XMLHttpRequest cannot load http://localhost:8081/Song/0. Origin http://localhost:8080 is not allowed by Access-Control-Allow-Origin.
EDIT
I've noticed that this is only happens when HTTP method is PUT or DELETE.
I can successfully make requests with GET or POST.
I'm making the request using jquery.
$.ajax({
url: Settings.RESTfulEndPointFor('Song/' + songID),
type: 'DELETE',
success: function (response) {
callback(response);
}
});
I don't know why, but it seems like this is resulting in method OPTIONS with Access-Control-Request-Method: DELETE.
Does any one know what causing this?
Any help is appreciated.
I had this problem when connecting to a WCF RESTful service via AJAX calls
My javascript was this:
var GetData= function(){
var data;
$.ajax({
url: this.server + "/data",
async: false,
type: "GET",
success: function (success) {
data = success;
}
});
return data;
};
My service endpoint was opened with this code
ServiceHost host = new ServiceHost(new MyService());
host.Open();
All the important data is stored in the App.config file, I did not have to change that file for this fix.
I knew I had to add the headers somewhere before the response message was sent.
After some searching and hacking I found the Authorization property of a ServiceHost object. The Authorization property is an instance of the ServiceAuthorizationBehavior class whose objects have a property called ServiceAuthorizationManager which is an instance of the ServiceAuthorizationManager class.
By creating a new class that inherits from the ServiceAuthorizationManager and setting it to the ServiceAuthorizationManager property of the Authorization behavior of your ServiceHost instance, you can intercept all calls to your service.
This is how I have implemented my class
public class MyServiceAuthorizationManager : ServiceAuthorizationManager
{
protected override bool CheckAccessCore(OperationContext operationContext)
{
HttpResponseMessageProperty prop = new HttpResponseMessageProperty();
prop.Headers.Add("Access-Control-Allow-Origin", "*");
operationContext.OutgoingMessageProperties.Add(HttpResponseMessageProperty.Name, prop);
return true;
}
}
then right after I declare my ServiceHost object (before the host is opened) I add this line
host.Authorization.ServiceAuthorizationManager = new MyServiceAuthorizationManager();
After doing this, rebuilding, and running my service the error message stopped showing up. Hooray!
Lastly, I read an article that described the ServiceHost class was designed for SOAP/WSDL services not RESTful services. For RESTful services the WebServiceHost object should be used.
So
ServiceHost host = new ServiceHost(new MyService());
host.Open();
becomes
WebServiceHost host = new WebServiceHost(new MyService());
host.Open();
You must add references to the following assemblies:
System.ServiceModel.Web
Hope this helps.
Sources:
http://social.msdn.microsoft.com/Forums/en/wcf/thread/97ddb118-fdfd-4651-9e61-4d822861325f
http://www.c-sharpcorner.com/uploadfile/dhananjaycoder/webservicehost-hosting-a-wcf-rest-service/
http://social.msdn.microsoft.com/forums/en-us/wcf/thread/551409FD-DD77-40EF-8B78-DC8B3D7EA0BA
Normally you put this in header of response. So put it in header where you modify/insert other header values like this
header('Access-Control-Allow-Origin: *) //change it according to however header is set in wcf , since this is php syntax
Point is your response should have this header.
The request you are seeing with the OPTIONS method and an Access-Control-Request-Method: DELETE header is called a "preflight request". The CORS specification requires this for requests with methods that have side effects (like DELETE) to ensure the resource is ok with the request.
Check out this section of the spec >>
http://www.w3.org/TR/cors/#cross-origin-request-with-preflight0
Unfortunately I don't know how to make this type of request work with wcf web api.
I have created
AllowCrossDomainRequestHandler : DelegatingChannel
and for each response I'm registering this header:
response.Headers.Add("Access-Control-Allow-Origin", "*");
I got this to work using the following response headers:
res.writeHead(200, {
'Content-Type': 'text/plain',
'Access-Control-Allow-Methods': 'DELETE, POST, GET, OPTIONS',
'Access-Control-Allow-Origin': '*'
});
First, with most web browsers there is no way to actually get around the cross-domain restriction. Most won't even let you change the "accept" header. So you have to use JSONP. JSONP is a way of getting JSON data from a cross-domain service, but it is returned in the form of a javascript snippet - which is allowed. The way it works is that you provide the callback function name to the service, then the cross-domain service returns a simple javascript with the actual JSON values embedded as the parameters to your callback function. This is really easy to do now with WCF WebApi (preview 6). Install it in VS 2010 with NuGet. Once you have it installed, look here for more information.

Resources