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

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.

Related

Azure functions & HTTP OPTIONS request

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

Angular2 http GET with Body?

I'm querying some elasticsearch servers from my Angular2 site. To help with security, we'd like to lock down access to only GET requests. Elasticsearch supports GET with a body but I'm having troubles making it happen with Angular2's http class.
this.http.post(SearchEndpoint, q.BuildPayload(), { method: 'GET' })
Since http.get doesn't have a body parameter, I am trying to use the post method. Previously I would leave off the RequestOptionsArgs of { method: 'GET' } and the POST would go through successfully with the body. By specifying the method in the third parameter the http class removes the body from the request.
Is it possible to make a GET request with a body in Angular 2?
I think that the raw XHR object doesn't allow this. To quote the specification (see https://xhr.spec.whatwg.org/):
4.5.6 The send() method
client . send([body = null])
Initiates the request. The optional argument provides the request body.
The argument is ignored if request method is GET or HEAD.
The send(body) method must run these steps:
If state is not opened, throw an InvalidStateError exception.
If the send() flag is set, throw an InvalidStateError exception.
If the request method is GET or HEAD, set body to null.
This discussion in the Postman github could also help you: https://github.com/postmanlabs/postman-app-support/issues/131.
If you want to query an ElasticSearch server, you can use POST requests. Here is a sample:
POST http://localhost:9200/myindex/mytype/_search?pretty=true
Content-Type: application/json
{
"query": {
"match": {
"somefield": "some value"
}
}
}
Hope it helps you,
Thierry
FWIW, I would be interested in hearing why this is desirable in https://github.com/whatwg/fetch/issues/83. For now there's no browser-based API that supports this, but we could offer it as a feature in fetch() given a convincing enough argument (and implementer interest).

CORS and ServiceStack Back End for Internal Web Apps

All,
We are trying to use ServiceStack at work as a backend API for all our internal and forward-facing sites, but we are running into problems. Here are the issues...
Sites
- site1.xyz.com
- site2.xyx.com
- etc.xyx.com
API
- api.xyx.com
1) We need a custom request header to handle the authentication. Our apps send an app ID to the API server to authenticate the app, so JSONP is out.
2) Since JSONP is out, we need to support OPTIONS. I have this working on Chrome and IE, but IE is throwing that damn security popup. We can solve that with our internal users, but not with our external users.
If anyone has any suggestions as to how to accomplish this, I'd love to hear them. I wish to hell the CORS spec handled subdomains. If it did, this would work and be sick simple...
I'm new to using CORS, but i did get it working with OPTIONS.
public class YourService : Service
{
...
/// <summary>
/// CORS support
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public object Options(YourRequestDto request)
{
// return HTTP Code and Location: header for the new resource
// 204 No Content; The request was processed successfully, but no response body is needed.
return new HttpResult()
{
StatusCode = HttpStatusCode.NoContent,
Headers = {
{ "Access-Control-Allow-Origin", "*" },
{ "Access-Control-Allow-Methods", "GET, OPTIONS" } ,
{ "Access-Control-Allow-Headers", "Content-Type" },
}
};
}
}
My reference was: servicestack REST API and CORS
The web browser should make the OPTIONS request, handled there. Then make the GET, POST, etc after.
This example allows all domains (*), but you could add your own logic to suit.
FYI- i do not think IE has full CORS support until IE 10.

JSONP request working cross-domain, but can't figure out origin

I'm trying out a JSONP call. I have a NodeJs app in server 1, under domain domain1.com looking like this:
server.get('/api/testjsonp', function(req, res) {
var clientId = req.param('clientId');
res.header('Content-Type', 'application/json');
res.header('Charset', 'utf-8')
res.send(req.query.callback + '({"something": "rather", "more": "fun",
"sourceDomain": "' + req.headers.origin + '"' + ',"clientId":"' + clientId +
'"});');
});
In another server (server 2) and under a different domain (domain2.com), I have created a test html page with a call like this:
var data = { clientId : 1234567890 };
$.ajax({
dataType: 'jsonp',
data: data,
jsonp: 'callback',
url: 'https://domain1.com/api/testjsonp?callback=1',
success: function(data) {
alert('success');
},
error: function(err){
alert('ERROR');
console.log(err);
}
});
I have 2 problems here:
1) Why is this working? Isn't it a cross-domain call and therefore I'd need to implement the ALLOW-ORIGIN headers stuff? I'm following this example:
http://css.dzone.com/articles/ajax-requests-other-domains
http://benbuckman.net/tech/12/04/cracking-cross-domainallow-origin-nut
2) In the server, I can't figure out which domain is making the call, req.headers.origin is always undefined. I'd like to be able to know which domain is calling, to prevent unwanted calls. Alternative I could check for the calling IP, any idea how?
Many thanks
Why is this working? Isn't it a cross-domain call and therefore I'd need to implement the ALLOW-ORIGIN headers stuff? I
Are far as the browser is concerned, you aren't directly reading data from a different origin. You are loading a JavaScript program from another origin (and it happens to have some data bundled in it).
In the server, I can't figure out which domain is making the call, req.headers.origin is always undefined. I'd like to be able to know which domain is calling, to prevent unwanted calls.
The URL of the referring page is stored in the Referer header, not the Origin header. It is, however, optional and won't be sent under many circumstances.
If you want to limit access to the data to certain sites, then you can't use JSON-P. Use plain JSON and CORS instead.
Alternative I could check for the calling IP, any idea how?
That would give you the address of the client, not the server that directed the client to you.

Get HttpResult using the JsonServiceClient

I am returning HttpResult from one of the rest service methods using servicestack's new API. Is there a way to get the HttpResult using the JsonServiceClient?
For ex: JSonServiceClient.Send<HttpResult>("DELETE","person", new { PersonID = 30 });
I want to inspect the header information from the httpresult.
Thanks.
There's no such thing as a HttpResult client response from a ServiceStack web service.
You use a HttpResult to customize the HTTP Response that's returned from your service, e.g. Add additional HTTP Headers. But the response body the client sees is still only the Response DTO (if any).
Use fiddler, wireshark, chome web inspector (if this is an Ajax call) or something like ServiceStack's Request Logger plugin to inspect the HTTP traffic.
Invalid use of ServiceStack's REST Clients
Also consider using the appropriate Clients REST API like client.Delete(), client.Get() etc instead of overloading the T.Send() method (which is usually a POST).
Use Typed DTOs in the ServiceClient instead of anonymous types which are not supported.
Inspecting HTTP Headers using the ServiceStack Service Clients
ServiceStack's Service Clients provide Local and Global WebResponse (and Request) filters that you can use to introspect the WebClient's HttpWebResponse returned for that request, e.g:
client.ResponseFilter = httpRes => {
httpRes.Headers.. //do something with returned headers
};
client.Delete(new Person { Id = 30, ...});

Resources