Как построить веб - "прокси" для API
Дорогой читатель,
Для проекта мне нужно частично выставить сторонний API на всеобщее обозрение. Для этого я думал, что могу легко получить входящий запрос, перенаправить его в API, получить ответ обратно и доставить ответ клиенту. Довольно простая концепция в теории, но почему-то проблематичная. Частично прокси работает, но когда я получаю доступ к прокси через браузер, некоторые данные выглядят одинаково, а другие-по-другому (json вместо XML), а некоторые я даже не могу отобразить (gzip chunked).
Пожалуйста, помогите (звучит действительно отчаянно, и я),
Реми Самульски
Что я уже пробовал:
Я построил веб-форму, которая примет запрос, создаст новый HttpRequestMessage и отправит его через HttpClient в API. Я получаю HttpResponseMessage, вытаскиваю содержимое (здесь часть GZIP идет неправильно) и отправляю его обратно через HttpResponse. Приведенный ниже код-это все, что необходимо для репликации с помощью онлайн-API OData. Следующие URL-адреса, похоже, работают аналогично в браузере через прокси-сервер или напрямую (в хорошем XML-представлении):
/Proxy2/
/Proxy2/$метаданные
Но это дает разные результаты:
/Proxy2/Customers (дает JSON, но непосредственно дает XML в обычном ASCII, без представления XML)
/Proxy2/Employees (дает ошибку, но непосредственно дает XML в обычном ASCII)
public class Global : HttpApplication { void Application_Start(object sender, EventArgs e) { // Code that runs on application startup GlobalConfiguration.Configure(WebApiConfig.Register); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); } protected void Application_BeginRequest(object sender, EventArgs e) { if ((Request.RawUrl.ToLower() + "/").StartsWith("/proxy2/") == true) { Context.RewritePath("~/_Proxy2.aspx", false); } } }
public partial class _Proxy2 : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { string url = Request.RawUrl.Replace("/Proxy2", "").TrimStart('/'); System.Net.Http.HttpRequestMessage httpRequestMessage = new System.Net.Http.HttpRequestMessage(System.Net.Http.HttpMethod.Get, "https://services.odata.org/V4/Northwind/Northwind.svc/" + url); Business.Http.AddHeaders(Request, httpRequestMessage); System.Net.Http.HttpResponseMessage httpResponseMessage; System.IO.Stream contentStream; using (System.Net.Http.HttpClient httpClient = new System.Net.Http.HttpClient()) { httpResponseMessage = httpClient.SendAsync(httpRequestMessage).Result; contentStream = httpResponseMessage.Content.ReadAsStreamAsync().Result; } Response.Clear(); Response.ClearHeaders(); Business.Http.AddHeaders(Response, httpResponseMessage); contentStream.CopyTo(Response.OutputStream); Response.End(); } }
public class Http { public static void AddHeaders(HttpRequest httpRequest, System.Net.Http.HttpRequestMessage httpRequestMessage) { foreach (string key in httpRequest.Headers.Keys) { string values = httpRequest.Headers[key]; System.Diagnostics.Debug.WriteLine("Request " + key + " : " + values); switch (key) { case "Host": //Removed due to SSL problems break; default: bool found = false; IEnumerable<string> valuesCurrent; if (httpRequestMessage.Headers.TryGetValues(key, out valuesCurrent) == true) { foreach (var item in valuesCurrent) { if (item.ToLower() == values.ToLower()) { found = true; break; } } } if (found == false) { httpRequestMessage.Headers.Add(key, values); } break; } } System.Diagnostics.Debug.WriteLine(""); Business.Reflection.DebugShowAllProperties(httpRequest); System.Diagnostics.Debug.WriteLine(""); Business.Reflection.DebugShowAllProperties(httpRequestMessage); System.Diagnostics.Debug.WriteLine(""); } public static void AddHeaders(HttpResponse httpResponse, System.Net.Http.HttpResponseMessage httpResponseMessage) { httpResponse.CacheControl = httpResponseMessage.Headers.CacheControl.ToString(); foreach (KeyValuePair<string, System.Collections.Generic.IEnumerable<string>> item in httpResponseMessage.Headers) { AddHeaders(httpResponse, item); } System.Diagnostics.Debug.WriteLine(""); foreach (KeyValuePair<string, System.Collections.Generic.IEnumerable<string>> item in httpResponseMessage.Content.Headers) { AddHeaders(httpResponse, item); } System.Diagnostics.Debug.WriteLine(""); Business.Reflection.DebugShowAllProperties(httpResponse); System.Diagnostics.Debug.WriteLine(""); Business.Reflection.DebugShowAllProperties(httpResponseMessage); System.Diagnostics.Debug.WriteLine(""); } private static void AddHeaders(HttpResponse httpResponse, KeyValuePair<string, System.Collections.Generic.IEnumerable<string>> keyValuePair) { string key = keyValuePair.Key; string values = ""; foreach (string stringValue in keyValuePair.Value) { if (values.Contains("," + stringValue) == false) { values += "," + stringValue; } } values = values.Trim(','); System.Diagnostics.Debug.WriteLine("Response " + key + " : " + values); switch (key) { case "Content-Type": httpResponse.ContentType = values; break; default: httpResponse.Headers.Add(key, values); break; } } }
public class Reflection { public static void DebugShowAllProperties(object obj) { var properties = GetProperties(obj); System.Diagnostics.Debug.WriteLine(obj.GetType().FullName); foreach (var p in properties) { string name = p.Name; string value = "NULL"; try { object valueObject = p.GetValue(obj, null); if (valueObject != null) { value = valueObject.ToString(); } } catch { } System.Diagnostics.Debug.WriteLine(name + " : " + value); } } private static System.Reflection.PropertyInfo[] GetProperties(object obj) { return obj.GetType().GetProperties(); } }