Mercurial > Grille > Grille-Config
diff Controllers/ReportController.cs @ 0:689cde763395
init cimmit
author | Franklin Schmit <meokcin@gmail.com> |
---|---|
date | Thu, 05 Sep 2024 10:16:16 +0800 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Controllers/ReportController.cs Thu Sep 05 10:16:16 2024 +0800 @@ -0,0 +1,243 @@ +using System; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Extensions; +using Microsoft.AspNetCore.Mvc; + +namespace Grille2.Controllers +{ + public partial class ReportController : Controller + { + [HttpGet("/__ssrsreport")] + public async Task Get(string url) + { + if (!String.IsNullOrEmpty(url)) + { + using (var httpClient = CreateHttpClient()) + { + var responseMessage = await ForwardRequest(httpClient, Request, url); + + CopyResponseHeaders(responseMessage, Response); + + await WriteResponse(Request, url, responseMessage, Response, false); + } + } + } + + [Route("/ssrsproxy/{*url}")] + public async Task Proxy() + { + var urlToReplace = String.Format("{0}://{1}{2}/{3}/", Request.Scheme, Request.Host.Value, Request.PathBase, "ssrsproxy"); + var requestedUrl = Request.GetDisplayUrl().Replace(urlToReplace, "", StringComparison.InvariantCultureIgnoreCase); + var reportServerIndex = requestedUrl.IndexOf("/ReportServer", StringComparison.InvariantCultureIgnoreCase); + if (reportServerIndex == -1) + { + reportServerIndex = requestedUrl.IndexOf("/Reports", StringComparison.InvariantCultureIgnoreCase); + } + var reportUrlParts = requestedUrl.Substring(0, reportServerIndex).Split('/'); + + var url = String.Format("{0}://{1}:{2}{3}", reportUrlParts[0], reportUrlParts[1], reportUrlParts[2], + requestedUrl.Substring(reportServerIndex, requestedUrl.Length - reportServerIndex)); + + using (var httpClient = CreateHttpClient()) + { + var responseMessage = await ForwardRequest(httpClient, Request, url); + + CopyResponseHeaders(responseMessage, Response); + + if (Request.Method == "POST") + { + await WriteResponse(Request, url, responseMessage, Response, true); + } + else + { + if (responseMessage.Content.Headers.ContentType != null && responseMessage.Content.Headers.ContentType.MediaType == "text/html") + { + await WriteResponse(Request, url, responseMessage, Response, false); + } + else + { + using (var responseStream = await responseMessage.Content.ReadAsStreamAsync()) + { + await responseStream.CopyToAsync(Response.Body, 81920, HttpContext.RequestAborted); + } + } + } + } + } + + partial void OnHttpClientHandlerCreate(ref HttpClientHandler handler); + + private HttpClient CreateHttpClient() + { + var httpClientHandler = new HttpClientHandler(); + + httpClientHandler.AllowAutoRedirect = true; + httpClientHandler.UseDefaultCredentials = true; + + if (httpClientHandler.SupportsAutomaticDecompression) + { + httpClientHandler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; + } + + OnHttpClientHandlerCreate(ref httpClientHandler); + + return new HttpClient(httpClientHandler); + } + + partial void OnReportRequest(ref HttpRequestMessage requestMessage); + + async Task<HttpResponseMessage> ForwardRequest(HttpClient httpClient, HttpRequest currentReqest, string url) + { + var proxyRequestMessage = new HttpRequestMessage(new HttpMethod(currentReqest.Method), url); + + foreach (var header in currentReqest.Headers) + { + if (header.Key != "Host") + { + proxyRequestMessage.Headers.TryAddWithoutValidation(header.Key, new string[] { header.Value }); + } + } + + this.OnReportRequest(ref proxyRequestMessage); + + if (currentReqest.Method == "POST") + { + using (var stream = new MemoryStream()) + { + await currentReqest.Body.CopyToAsync(stream); + stream.Position = 0; + + string body = new StreamReader(stream).ReadToEnd(); + proxyRequestMessage.Content = new StringContent(body); + + if (body.IndexOf("AjaxScriptManager") != -1) + { + proxyRequestMessage.Content.Headers.Remove("Content-Type"); + proxyRequestMessage.Content.Headers.Add("Content-Type", new string[] { currentReqest.ContentType }); + } + } + } + + return await httpClient.SendAsync(proxyRequestMessage); + } + + static void CopyResponseHeaders(HttpResponseMessage responseMessage, HttpResponse response) + { + response.StatusCode = (int)responseMessage.StatusCode; + foreach (var header in responseMessage.Headers) + { + response.Headers[header.Key] = header.Value.ToArray(); + } + + foreach (var header in responseMessage.Content.Headers) + { + response.Headers[header.Key] = header.Value.ToArray(); + } + + response.Headers.Remove("transfer-encoding"); + } + + static async Task WriteResponse(HttpRequest currentReqest, string url, HttpResponseMessage responseMessage, HttpResponse response, bool isAjax) + { + var result = await responseMessage.Content.ReadAsStringAsync(); + + var ReportServer = url.Contains("/ReportServer/", StringComparison.InvariantCultureIgnoreCase) ? "ReportServer" : "Reports"; + + var reportUri = new Uri(url); + var proxyUrl = String.Format("{0}://{1}{2}/ssrsproxy/{3}/{4}/{5}", currentReqest.Scheme, currentReqest.Host.Value, currentReqest.PathBase, + reportUri.Scheme, reportUri.Host, reportUri.Port); + + if (isAjax && result.IndexOf("|") != -1) + { + var builder = new StringBuilder(); + + var delimiterIndex = 0; + var length = 0; + var index = 0; + + var type = ""; + var id = ""; + var content = ""; + + while (index < result.Length) + { + delimiterIndex = result.IndexOf("|", index); + if (delimiterIndex == -1) + { + break; + } + length = int.Parse(result.Substring(index, delimiterIndex - index)); + if ((length % 1) != 0) + { + break; + } + index = delimiterIndex + 1; + delimiterIndex = result.IndexOf("|", index); + if (delimiterIndex == -1) + { + break; + } + type = result.Substring(index, delimiterIndex - index); + index = delimiterIndex + 1; + delimiterIndex = result.IndexOf("|", index); + if (delimiterIndex == -1) + { + break; + } + id = result.Substring(index, delimiterIndex - index); + index = delimiterIndex + 1; + if ((index + length) >= result.Length) + { + break; + } + content = result.Substring(index, length); + index += length; + if (result.Substring(index, 1) != "|") + { + break; + } + index++; + + content = content.Replace($"/{ReportServer}/", $"{proxyUrl}/{ReportServer}/", StringComparison.InvariantCultureIgnoreCase); + if (content.Contains("./ReportViewer.aspx", StringComparison.InvariantCultureIgnoreCase)) + { + content = content.Replace("./ReportViewer.aspx", $"{proxyUrl}/{ReportServer}/Pages/ReportViewer.aspx", StringComparison.InvariantCultureIgnoreCase); + } + else + { + content = content.Replace("ReportViewer.aspx", $"{proxyUrl}/{ReportServer}/Pages/ReportViewer.aspx", StringComparison.InvariantCultureIgnoreCase); + } + + builder.Append(String.Format("{0}|{1}|{2}|{3}|", content.Length, type, id, content)); + } + + result = builder.ToString(); + } + else + { + result = result.Replace($"/{ReportServer}/", $"{proxyUrl}/{ReportServer}/", StringComparison.InvariantCultureIgnoreCase); + + if (result.Contains("./ReportViewer.aspx", StringComparison.InvariantCultureIgnoreCase)) + { + result = result.Replace("./ReportViewer.aspx", $"{proxyUrl}/{ReportServer}/Pages/ReportViewer.aspx", StringComparison.InvariantCultureIgnoreCase); + } + else + { + result = result.Replace("ReportViewer.aspx", $"{proxyUrl}/{ReportServer}/Pages/ReportViewer.aspx", StringComparison.InvariantCultureIgnoreCase); + } + } + + response.Headers.Remove("Content-Length"); + response.Headers.Append("Content-Length", new string[] { System.Text.Encoding.UTF8.GetByteCount(result).ToString() }); + + await response.WriteAsync(result); + } + } +}