There’s a mobile app that I’m working on that will be performing complex queries against a database that is exposed via an OData api. One small hitch is that the mobile app is not allowed to access the OData api directly, but I can implement a proxy that will have access to the OData api and is deployed in a place that the mobile app can access. While I do not want to try and consume the request from the mobile app, I would like the ability to perform some logic before and after the request is forwarded in order to allow for either logging or validation purposes.
What I have created is a simple ASP.NET api that forwards requests to a configured host and returns the results. Any path or query string parameters are passed on to the new host just as they are received. It supports the Http Methods GET, PUT, POST, PATCH, and DELETE.
The desired target host is configured in the web.config file AppSettings:
<appSettings> <add key="TargetHost" value="http://services.odata.org/V3/Northwind/Northwind.svc"/> </appSettings>
The ProxyController only has one endpoint that is used to catch all requests and forward them to the configured host, returning the results.
[HttpGet, HttpPost, HttpPut, HttpPatch, HttpDelete] [Route("{*remaining}")] public Task SendMessage() { // Create a new Uri using the configured host. This is where the request will be forwarded. // The host value is configured in the web.config file string targetHost = ConfigurationManager.AppSettings.Get("TargetHost"); string forwardUri = targetHost + Request.RequestUri.PathAndQuery; // Update the request with the new Uri Request.Headers.Remove("Host"); Request.RequestUri = new Uri(forwardUri); if (Request.Method == HttpMethod.Get) { Request.Content = null; } // Call the configured host and return the result of the request var client = new HttpClient(); return client.SendAsync(Request, HttpCompletionOption.ResponseHeadersRead); }
In order to allow custom logic before or after the call to the OData api, there is a CustomFilter that is added to the ProxyController. It contains two methods that allow you to perform logic before the request is forwarded, and before results are returned to the caller:
public override void OnActionExecuting(HttpActionContext actionContext) { // Put logic here that should be performed before requests are forwarded base.OnActionExecuting(actionContext); } public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) { // Put logic here that should be performed after requests are forwarded, but before the results are returned to the caller base.OnActionExecuted(actionExecutedContext); }
When using this proxy, the user (or mobile app, in this instance) is not aware that any forwarding has happened, and it appears that all path and query parameters have been handled by the highly complex api that I built! Notice how the URL in the browser still shows the url for my Proxy api:
When the results are coming from the sample OData service at http://services.odata.org/V3/Northwind/Northwind.svc:
You can find the code for this project on my GitHub account here: https://github.com/danksalot/ApiProxy