How to add CORS middleware in shelf with router? - dart

I am new to server side programming with dart. I made a simple API server with a number of get routes. I am handling this as follow,
Router router = Router();
router.get('/', checkSTATUS);
router.get('/login/<user>/<pass>', (Request request, String user, String pass) async {
id = 0;
// stuff
return Response.ok(json.encode({"status":"found","id":id}));
});
router.get('/update', (Request request) async {
//stuff
return Response.ok(json.encode({"status": "updated", "data": updated}));
});
//for any other requests
router.all('/<ignored|.*>', (Request request) {
return Response.notFound(json.encode('Page not found'));
});
final server = await serve(
router,
InternetAddress.anyIPv4,
8080,
);
I can access these routes using postman but making requests using flutter web results in error. I searched and found out that this may be CORS related. But how do I add the CORS headers without disrupting the entire code.

Please refer this document. https://pub.dev/packages/shelf_cors_headers.
Install this package

Related

Is there a way to change http request method in netflix zuul routing filter?

I'm trying to trasform http GET method call from legacy api server built with MVC1 pattern to new restful api server without any change of front-end source code using netflix zuul and eureka.
I added zuul pre filter transforming legacy url to restful convention url working after PreDecorationFilter and it works fine.
But now I'm facing problem converting the GET method to proper method like POST, PUT, DELETE by distinguising url so that the requests are properly mapped in spring controller via #GetMapping/#PostMapping/#PutMapping/#DeleteMapping.
I looked into SimpleRoutingFilter that handles HttpClient but
Because of environmental constraint, I have to use eureka service id to route to the new api server and that means I should use RibbonRoutingFilter which is quite complicated to find out a right place to this operation in.
So, is this possible to change http method or make new http request before RibbonRoutingFilter?
If possible can you please suggest where is the right place to do that or some reference?
Many thanks!
======================================================================
Milenko Jevremovic,
Would you please tell me more detail about using Feign?
I defiend #FeignClient like below
#PostMapping(value = "{url"}, consumes = "application/json")
ResponseEntity<?> postMethod(#PathVariable("url") String url);
and to get query parameters to request body for POST In zuul pre filter,
after transform logic from GET request url to POST new restful url ...
byte[] bytes = objectMapper.writeValueAsBytes(ctx.get("requestQueryParams"));
ctx.setRequests(new HttpServletRequestWrapper(request) {
#Override ..getMethod
#Override ..getContentLength
#Override ..getConentLengthLong
#Override
public ServletInputStream getInputStream() {
return new ServletInputStreamWrapper(bytes);
}
}
ResponseEntity<?> response feignClient.post(transformedNewApiUri);
and set RequestContext code that you suggested ....
and controller of new api server is like,
#PostMapping
ResponseEntity<model> post(#RequestBody req..)
It comes to controller fine but when I see the http request in post method of controller,
There is no request body for parameters.
(HttpServleterRequest getInputStream shows empty)
The request data set in zuul pre filter by HttpServletRequestWrapper is
not used in Feign maybe...?
Would you please get me more idea setting request body when changing GET query
to POST constructor for using Feign?
It is not possible to change method of HttpServletRequest, but it's possible to replace request in RequestContext. HttpServletRequestWrapper appears to be very helpful:
static class PostHttpServletRequest extends HttpServletRequestWrapper {
public PostHttpServletRequest(HttpServletRequest request) {
super(request);
}
#Override
public String getMethod() {
return "POST";
}
}
So method run can be rewritten as following:
#Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
HttpServletRequest requestWrapper = new PostHttpServletRequest(request);
ctx.setRequest(requestWrapper);
return null;
}
After doing some research did not find any built in solution.
But what comes in my mind you can use Feign client in your Pre filter, get the response, set the response and return it immediately to client from your Pre filter.
You can set Feign client url or your service id, like it is explained in the docs, it uses ribbon as well .
Change response in your run method like:
...
RequestContext ctx = RequestContext.getCurrentContext();
ctx.setResponseStatusCode(your_code);
ctx.setResponseBody(new_body);
ctx.setSendZuulResponse(false);
return null

Implementing Message Handlers in MVC 6

I have current API (web api 2) project that has a number of message handlers in use, some run for every request (checking to make sure the request is https and the request is coming from an authorised client) and some that run on specific routes (checking for the existence of a security token).
Now my question is how do I replicate this functionality in MVC 6, my current understanding is that it should be done through the use of middleware but I've not found an example that allows me to inspect the headers of the incoming request and should they not be what they are supposed to be return the appropriate http response code.
Middleware is definitely the right option to solve what you're looking to solve. I wrote a decent explanation about using/writing middlware here: ASP.NET MVC 6 handling errors based on HTTP status code
To specifically answer how to inspect headers here's an example:
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
if (!string.Equals(context.Request.Headers["myheader"], "somevalue", StringComparison.Ordinal))
{
context.Response.StatusCode = 400;
await context.Response.WriteAsync("Invalid headers");
}
else
{
await next();
}
});
}
}

How to intercept a 404 Not Found using the OWIN pipeline

I have another question to do with Web-API and OWIN. I am "playing" with it, trying to learn about it, and I wanted to see if I could intercept a 404 on the "way back" from the web api.
So, I have the following in my Startup..
app.Use(async (environment, next) =>
{
Debug.WriteLine(environment.Request.Uri);
await next();
Debug.WriteLine(environment.Response.StatusCode);
});
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseWebApi(config);
I then do a GET (in a browser) using an invalid URI so that I get a 404 result. I expected to see this as the status code written out in the Debug.WriteLine(environment.Response.StatusCode)
However, all I see (in dev studio output window , as I am running IIS express) is
http://localhost:55905/myresource
http://localhost:55905/myresource
200
200
I really expected to the the 404 in there.
Does anyone know why we don't see the 404 coming back?
I have looked through the Response, and cannot see it anywhere.
Thanks in advance for any help!
Is /myresource a valid webapi route?
I think (but I'm not sure) your request is handled by IIS directly ignoring the owin-pipeline. But I don't know why its responding with a 200.
You can test it really easy.
Assuming your code and the following configuration:
public static class WebApiConfig {
public static void Register(HttpConfiguration config) {
config.Routes.MapHttpRoute(
name: "API Default",
routeTemplate: "api/{controller}/{id}",
defaults: new {id = RouteParameter.Optional}
);
}
}
And modified your Startup class a little:
app.Use(async (environment, next) => {
Debug.WriteLine(environment.Request.Uri);
environment.Response.OnSendingHeaders(_ => {
var resp = ((IOwinResponse) _);
Debug.WriteLine("Headers are send!: {0}", resp.StatusCode);
resp.Headers.Add("X-MyTag", new[] {"Nice value!"});
}, environment.Response);
await next();
Debug.WriteLine(environment.Response.StatusCode);
});
Sample controller:
public class ValuesController : ApiController {
// GET api/<controller>
public IEnumerable<string> Get() {
return new string[] { "value1", "value2" };
}
}
Now the OWIN Pipeline should return in EACH request a custom header X-MyTag.
I'm using Fiddler to inspect my request.
A request to http://localhost:13543/ responds without my header. So it isn't served by the owin pipeline.
On the other hand a request to http://localhost:13543/api/Values responds with a 200 and my custom header.
An (invalid) request to http://localhost:13543/api/Values1 responds with 404 including my custom header AND you can see this 404 in your output console.

Dart request succeeding ... somehow?

I'm developing a dart application which will consume a REST service I'm building. I started writing out the dart code to perform an ajax request to my login endpoint. However, even when my dart ajax request should fail, it claims to succeed.
I don't have any services up and running (and even if I did it would be using the wrong domain / port right now), but this code gives a 200 OK HttpResponse every time:
class PlayerController {
const PlayerController();
static const String LOGIN_URL = "login";
void login(String username, String password) {
Map<String, String> headers = {"Content-Type": "application/x-www-form-urlencoded"};
String body = "j_username=$username&j_password=$password&submit=Login";
HttpRequest.request(LOGIN_URL, method: "POST", requestHeaders: headers, sendData: body)
.then((request) => processLogin(request, username))
.catchError((e) => processLoginError(e));
}
void processLogin(var whatIsThis, String username) {
query("#loginButton").text = "Logout";
//TODO get the player then set them
}
void processLoginError(var e) {
print("total failure to login because of $e");
}
}
It always hits the processLogin method, and never hits the processLoginError method. Does anyone have any idea why this would be? Should I be performing this ajax request in a different way? (If you couldn't guess, it will be signing into spring security).
I read somewhere that file system requests always succeed. Is Dart somehow making this a file system request rather than a web request?
This is because the request actually completes successfully.
Your request to "login" will actually call http://127.0.0.1:6521/[Path_to_your_Dart_file]/login
The server started by Dart when running in Dartium (127.0.0.1:6521) seems to answer to every POST request with HTTP 200 and an empty response body.
If you change the method from POST to GET, it will fail as expected.
As for why the server does this - I don't really know. This would have to be answered by the Dart team.

GetClientAccessToken having clientIdentifier overwritten to null by NetworkCredential

I've been trying to get the GetClientAccessToken flow to work with the latest release 4.1.0 (via nuget), where I'm in control of all three parties: client, authorization server and resource server.
The situation I have started to prototype is that of a Windows client app (my client - eventually it will be WinRT but its just a seperate MVC 4 app right now to keep it simple), and a set of resources in a WebAPI project. I'm exposing a partial authorization server as a controller in the same WebAPI project right now.
Every time (and it seems regardless of the client type e.g. UserAgentClient or WebServerClient) I try GetClientAccessToken, by the time the request makes it to the auth server there is no clientIdentifier as part of the request, and so the request fails with:
2012-10-15 13:40:16,333 [41 ] INFO {Channel} Prepared outgoing AccessTokenFailedResponse (2.0) message for <response>:
error: invalid_client
error_description: The client secret was incorrect.
I've debugged through the source into DNOA and essentially the credentials I'm establishing on the client are getting wiped out by NetworkCredential.ApplyClientCredential inside ClientBase.RequestAccessToken. If I modify clientIdentifier to something reasonable, I can track through the rest of my code and see the correct lookups/checks being made, so I'm fairly confident the auth server code is ok.
My test client currently looks like this:
public class AuthTestController : Controller
{
public static AuthorizationServerDescription AuthenticationServerDescription
{
get
{
return new AuthorizationServerDescription()
{
TokenEndpoint = new Uri("http://api.leave-now.com/OAuth/Token"),
AuthorizationEndpoint = new Uri("http://api.leave-now.com/OAuth/Authorise")
};
}
}
public async Task<ActionResult> Index()
{
var wsclient = new WebServerClient(AuthenticationServerDescription, "KieranBenton.LeaveNow.Metro", "testsecret");
var appclient = new DotNetOpenAuth.OAuth2.UserAgentClient(AuthenticationServerDescription, "KieranBenton.LeaveNow.Metro", "testsecret");
var cat = appclient.GetClientAccessToken(new[] { "https://api.leave-now.com/journeys/" });
// Acting as the Leave Now client we have access to the users credentials anyway
// TODO: CANNOT do this without SSL (turn off the bits in web.config on BOTH sides)
/*var state = client.ExchangeUserCredentialForToken("kieranbenton", "password", new[] { "https://api.leave-now.com/journeys/" });
// Attempt to talk to the APIs WITH the access token
var resourceclient = new OAuthHttpClient(state.AccessToken);
var response = await resourceclient.GetAsync("https://api.leave-now.com/journeys/");
string sresponse = await response.Content.ReadAsStringAsync();*/
// A wrong one
/*var wresourceclient = new OAuthHttpClient("blah blah");
var wresponse = await wresourceclient.GetAsync("https://api.leave-now.com/journeys/");
string wsresponse = await wresponse.Content.ReadAsStringAsync();
// And none
var nresourceclient = new HttpClient();
var nresponse = await nresourceclient.GetAsync("https://api.leave-now.com/journeys/");
string nsresponse = await nresponse.Content.ReadAsStringAsync();*/
return Content("");
}
}
I can't figure out how to prevent this or if its by design what I'm doing incorrectly.
Any help appreciated.
The NetworkCredentialApplicator clears the client_id and secret from the outgoing message as you see, but it applies it as an HTTP Authorization header. However, HttpWebRequest clears that header on the way out, and only restores its value if the server responds with an HTTP error and a WWW-Authenticate header. It's quite bizarre behavior on .NET's part, if you ask me, to suppress the credential on the first outbound request.
So if the response from the auth server is correct (at least, what the .NET client is expecting) then the request will go out twice, and work the second time. Otherwise, you might try using the PostParameterApplicator instead.

Resources