Is it possible to return promise object from requestInterceptor, will swagger client wait for the promise returned to resolve before invoking actual http call ?
Yes, this is supported in Swagger UI 3.13.3+. From the documentaton (emphasis mine):
requestInterceptor
Function=(a => a). MUST be a function. Function to intercept remote definition, Try-It-Out, and OAuth2 requests. Accepts one argument requestInterceptor(request) and must return the modified request, or a Promise that resolves to the modified request.
Related
I have a main REST web app where I have an endpoint: POST /api/v1/my_endpoint
I want to allow it to be called:
1) via a browser via ajax from my other web apps on different domains
2) from a server side via HTTP client library.
In the case of ajax call - #1 - I'll have to include "Allow-Control-Allow-Origin" and the similar headers to my response to let a browser receive a response.
In the case #2 - I won't need to include those headers.
However, there's no reliable way to distinguish between #1 and #2.
How can I solve that?
On the server, you check for the presence of an Origin header. This header is sent by the browser as part of the CORS protocol. To explain how it works, below is a filter (in other frameworks, this is also known as middleware) used by a Jersey application. Jersey is a Java REST framework. Sorry I don't know Rails. But you should still be able to follow along with this explanation,.
How this filter works is that the ContiainerRequestFilter is called before the backend controller method is called, then the controller method is called, then the ContainerResponseFilter is called. See the commented notes above the methods to see which method are for which.
public class CorsFilter implements ContainerRequestFilter, ContainerResponseFilter {
#Override
// ******************************************
// implementation for ContainerRequestFilter
// ******************************************
public void filter(ContainerRequestContext request) throws IOException {
if (isPreflightRequest(request)) {
request.abortWith(Response.ok().build());
return;
}
}
private static boolean isPreflightRequest(ContainerRequestContext request) {
return request.getHeaderString("Origin") != null
&& request.getMethod().equalsIgnoreCase("OPTIONS");
}
#Override
// ******************************************
// implementation for ContainerResponseFilter
// ******************************************
public void filter(ContainerRequestContext request, ContainerResponseContext response)
throws IOException {
if (request.getHeaderString("Origin") == null) {
return;
}
if (isPreflightRequest(request)) {
response.getHeaders().add("Access-Control-Allow-Credentials", "true");
response.getHeaders().add("Access-Control-Allow-Methods",
"GET, POST, PUT, DELETE, OPTIONS, HEAD");
response.getHeaders().add("Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, Authorization, X-CSRF-Token, " +
"Accept-Version, Content-Length, Content-MD5, Date, X-Api-Version, X-File-Name");
}
response.getHeaders().add("Access-Control-Allow-Origin", "*");
}
}
So when the request comes in, the filter checks to see if it is Preflight request. There are two types of cross origin request: a normal one, and preflight. The preflight request occurs before the actual request is made to the server. This is an OPTIONS request where the browser sends some CORS request headers to check with the server to see if the request is allowed. The server should respond back with CORS response headers telling the server that the request is allowed.
So with this filter, is it a preflight request, we abort the request (the controller method will not be called) and then the code execution goes to the ContainerResponseFilter where we set the CORS response headers. You can see in the code, we check the same isPreflightRequest() method.
If the request is not an OPTIONS request, and the Origin header is present, then it is a "normal" cross origin request, in which case, all that is required in in the response headers is Access-Control-Allow-Origin.
Notice that if there is no Origin header, then no CORS headers are added. This is basically how you will differentiate from an AJAX client and other HTTP clients. Only AJAX requests will add the Origin header, and this is done automatically by the browser when it detects a cross origin request.
I hope you understand everything I am talking about, even though the code is Java. It think it's pretty straight forward though, even if you have never used Java. The naming or methods and variables should make it easy to follow. If you understand the flow of the code, then you should pretty much understand the flow of the CORS protocol.
Aside
As an aside, it doesn't hurt if you add the Access-Control-Allow-Origin header on all responses, whether it be an AJAX request or an HTTP client request. If you want to be lazy and implement it this way, it won't hurt. It is required for the AJAX client, but not for the HTTP client. But if you include it in the HTTP client, nobody will die. The world will go on business as usual.
I have an interceptor using $httpProvider as follwos (taken from Angular doc)
$httpProvider.interceptors.push(function ($q) {
return {
'response': function (response) {
// look for the antiforgerytoken and update dataService with the same.
return response || $q.when(response);
}
};
});
using the debugger I see that this method is called on each response and when I look at the 'response' object pased I see only one header, namely the Accept-Header as shown below
When I look at the response packet in the chrome I see many more headers
My question is why am I not able to see all the headers in the response?
Specifically I want to read the cookie for AntiforgeryToken and store it, how can I do that?
I believe the cookie AntiforgeryToken is a HttpOnly cookie and cannot be accessed from javascript. Can you check
See some details here http://blog.codinghorror.com/protecting-your-cookies-httponly/
Such cookies are mean for server exclusively.
I have never used JUnit or other testing frameworks. All i know is how to develop rest service. I recently saw REST assured framework to test REST api. But all the articles that i found looks like below. But i don't know how to pass request xml and how will i get response and when should i call this method.?
Do i need to use some other tool before this REST assured.? I am completely beginner in this kind of testing frameworks. Please show me some light in this world. All i know is how to send request and check values in the response in SOAPUI. I have never tried this.
expect().
statusCode(200).
body(
"user.email", equalTo("test#hascode.com"),
"user.firstName", equalTo("Tim"),
"user.lastName", equalTo("Testerman"),
"user.id", equalTo("1")).
when().
get("/service/single-user/xml");
expect() /* what u expect after sending a request to REST Service */
statusCode(200) /*you are expecting 200 as statuscode which tells request handled successfully at server */
body()
/* the conditions given in body are compare the value with expected values. "equalTo" hamcrest matcher condition (you need to have hamcrest jar in java classpath).*/
when(). /* as is name says above all will be done after sending get/post/put/delete request right so before you put these get,post,put,delete you will have this method as prefix */
get("/service/single-user/xml")
/* the actual REST API request url goes here. can be GET/POST/PUT/DELETE. the confusion for you is its only showing half part which is base path.you can give entire request url in get() method.*/
more on:
http://rest-assured.googlecode.com/svn/tags/1.8.1/apidocs/com/jayway/restassured/RestAssured.html
I hope this helps.
How do I invoke a Service Operation in WCF from iOS?
I have a Service Operation defined in my WCF Data Service (tied to a stored procedure in my DB schema) that I need to invoke from iOS. Say I've got the following declaration in my .svc.cs file:
[WebInvoke(RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
public IQueryable<Foo> GetFoos(int param1, DateTime param2, string param3)
{
return CurrentDataSource.GetFoos(param1, param2, param3).AsQueryable();
}
And I've got it set up with the proper rights in InitializeService:
config.SetServiceOperationAccessRule("GetFoos", ServiceOperationRights.AllRead);
When I try to invoke this via HTTP POST from iOS, I get back an error wrapped in JSON:
Bad Request - Error in query syntax.
It seems like it doesn't like how I'm passing my parameters. I'm passing them JSON-encoded (using NSJSONSerialization to turn an NSDictionary into a JSON string) in the request body of a POST request. The same method works on another web service (.svc) not connected to WCF that has operations annotated the same way.
An answer to another question of mine in a similar vein suggests that data formats can be negotiated between client and server, and I've read that dates are a pain to format, so maybe it's my DateTime parameter that's a problem. But I've tried both the JSON format (\/Date(836438400000)\/ and /Date(836438400000)/) and the JSON Light format (1996-07-16T00:00:00) to no avail.
So my question is this: what is the proper way to invoke this operation? If I need to have my app tell the server what format to expect, how do I do that?
Update: I tried using the format datetime'1996-07-16T00:00:00' as mentioned in this question. Same error.
Update 2: The MSDN page for Service Operations seems to suggest that nothing besides Method = "POST" is supported when annotating the WebInvoke for a Service Operation. I tried removing everything from what is quoted in the above code and setting the method to POST. Same error.
Update 3: On Pawel's suggestion, I made a new Service Operation on my Data Service just like this:
[WebInvoke(Method = "POST")]
public IQueryable<string> GetFoos()
{
List<string> foos = new List<string>();
foos.Add("bar");
return foos.AsQueryable();
}
I was able to make it work in Fiddler's Composer pane by setting the method to POST, adding accept:application/json;charset=utf-8 and Content-Length:0 to the headers. Then I added a single int parameter to the operation (called param1). I set the body of my request in Fiddler to {"param1":"1"} and ran it (and Fiddler automatically updated my content-length header), and got the same error. I changed the type of my parameter to string and ran my request again and it worked. So my problem seems to be non-string types.
You need to send parameters in the Url and not in the request body.
I am making a POST request with RestSharp (on windows phone 7.1 client). I sent string to a service in a request body. Looks like the service is successfully called and it returns proper value (integer), however response object is null:
client.ExecuteAsync<T>(request, (response) => {
data = response.Data; // response is null in debugger
});
I cant understand why is that so.
<T> isn't a valid value for that call. I'm not sure that would even build there unless you've wrapped it in a generic method.
Also, is the response coming back as plain text? What's the Content-Type returned? Most likely, you should just use ExecuteAsync(request, callback) without the generic parameter and grab the data out of response.Content which is a string of the response body. response.Data is for the automatically deserialized XML or JSON (or custom) response if you use the generic method overload that specifies a type to deserialize to.
This seems to be an ongoing issue with RestSharp asynchronous calls - for HTTP transport errors ErrorException object is useless (returns null). Check the StatusCode property if it returns with anything but HttpStatusCode.OK. StatusDescription is not extremely useful either as it doesn't match complete status message from server response payload.