0
|
1 using System;
|
|
2 using System.IO;
|
|
3 using System.Linq;
|
|
4 using System.Net;
|
|
5 using System.Net.Http;
|
|
6 using System.Text;
|
|
7 using System.Text.RegularExpressions;
|
|
8 using System.Threading.Tasks;
|
|
9 using Microsoft.AspNetCore.Http;
|
|
10 using Microsoft.AspNetCore.Http.Extensions;
|
|
11 using Microsoft.AspNetCore.Mvc;
|
|
12
|
|
13 namespace Grille2.Controllers
|
|
14 {
|
|
15 public partial class ReportController : Controller
|
|
16 {
|
|
17 [HttpGet("/__ssrsreport")]
|
|
18 public async Task Get(string url)
|
|
19 {
|
|
20 if (!String.IsNullOrEmpty(url))
|
|
21 {
|
|
22 using (var httpClient = CreateHttpClient())
|
|
23 {
|
|
24 var responseMessage = await ForwardRequest(httpClient, Request, url);
|
|
25
|
|
26 CopyResponseHeaders(responseMessage, Response);
|
|
27
|
|
28 await WriteResponse(Request, url, responseMessage, Response, false);
|
|
29 }
|
|
30 }
|
|
31 }
|
|
32
|
|
33 [Route("/ssrsproxy/{*url}")]
|
|
34 public async Task Proxy()
|
|
35 {
|
|
36 var urlToReplace = String.Format("{0}://{1}{2}/{3}/", Request.Scheme, Request.Host.Value, Request.PathBase, "ssrsproxy");
|
|
37 var requestedUrl = Request.GetDisplayUrl().Replace(urlToReplace, "", StringComparison.InvariantCultureIgnoreCase);
|
|
38 var reportServerIndex = requestedUrl.IndexOf("/ReportServer", StringComparison.InvariantCultureIgnoreCase);
|
|
39 if (reportServerIndex == -1)
|
|
40 {
|
|
41 reportServerIndex = requestedUrl.IndexOf("/Reports", StringComparison.InvariantCultureIgnoreCase);
|
|
42 }
|
|
43 var reportUrlParts = requestedUrl.Substring(0, reportServerIndex).Split('/');
|
|
44
|
|
45 var url = String.Format("{0}://{1}:{2}{3}", reportUrlParts[0], reportUrlParts[1], reportUrlParts[2],
|
|
46 requestedUrl.Substring(reportServerIndex, requestedUrl.Length - reportServerIndex));
|
|
47
|
|
48 using (var httpClient = CreateHttpClient())
|
|
49 {
|
|
50 var responseMessage = await ForwardRequest(httpClient, Request, url);
|
|
51
|
|
52 CopyResponseHeaders(responseMessage, Response);
|
|
53
|
|
54 if (Request.Method == "POST")
|
|
55 {
|
|
56 await WriteResponse(Request, url, responseMessage, Response, true);
|
|
57 }
|
|
58 else
|
|
59 {
|
|
60 if (responseMessage.Content.Headers.ContentType != null && responseMessage.Content.Headers.ContentType.MediaType == "text/html")
|
|
61 {
|
|
62 await WriteResponse(Request, url, responseMessage, Response, false);
|
|
63 }
|
|
64 else
|
|
65 {
|
|
66 using (var responseStream = await responseMessage.Content.ReadAsStreamAsync())
|
|
67 {
|
|
68 await responseStream.CopyToAsync(Response.Body, 81920, HttpContext.RequestAborted);
|
|
69 }
|
|
70 }
|
|
71 }
|
|
72 }
|
|
73 }
|
|
74
|
|
75 partial void OnHttpClientHandlerCreate(ref HttpClientHandler handler);
|
|
76
|
|
77 private HttpClient CreateHttpClient()
|
|
78 {
|
|
79 var httpClientHandler = new HttpClientHandler();
|
|
80
|
|
81 httpClientHandler.AllowAutoRedirect = true;
|
|
82 httpClientHandler.UseDefaultCredentials = true;
|
|
83
|
|
84 if (httpClientHandler.SupportsAutomaticDecompression)
|
|
85 {
|
|
86 httpClientHandler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
|
|
87 }
|
|
88
|
|
89 OnHttpClientHandlerCreate(ref httpClientHandler);
|
|
90
|
|
91 return new HttpClient(httpClientHandler);
|
|
92 }
|
|
93
|
|
94 partial void OnReportRequest(ref HttpRequestMessage requestMessage);
|
|
95
|
|
96 async Task<HttpResponseMessage> ForwardRequest(HttpClient httpClient, HttpRequest currentReqest, string url)
|
|
97 {
|
|
98 var proxyRequestMessage = new HttpRequestMessage(new HttpMethod(currentReqest.Method), url);
|
|
99
|
|
100 foreach (var header in currentReqest.Headers)
|
|
101 {
|
|
102 if (header.Key != "Host")
|
|
103 {
|
|
104 proxyRequestMessage.Headers.TryAddWithoutValidation(header.Key, new string[] { header.Value });
|
|
105 }
|
|
106 }
|
|
107
|
|
108 this.OnReportRequest(ref proxyRequestMessage);
|
|
109
|
|
110 if (currentReqest.Method == "POST")
|
|
111 {
|
|
112 using (var stream = new MemoryStream())
|
|
113 {
|
|
114 await currentReqest.Body.CopyToAsync(stream);
|
|
115 stream.Position = 0;
|
|
116
|
|
117 string body = new StreamReader(stream).ReadToEnd();
|
|
118 proxyRequestMessage.Content = new StringContent(body);
|
|
119
|
|
120 if (body.IndexOf("AjaxScriptManager") != -1)
|
|
121 {
|
|
122 proxyRequestMessage.Content.Headers.Remove("Content-Type");
|
|
123 proxyRequestMessage.Content.Headers.Add("Content-Type", new string[] { currentReqest.ContentType });
|
|
124 }
|
|
125 }
|
|
126 }
|
|
127
|
|
128 return await httpClient.SendAsync(proxyRequestMessage);
|
|
129 }
|
|
130
|
|
131 static void CopyResponseHeaders(HttpResponseMessage responseMessage, HttpResponse response)
|
|
132 {
|
|
133 response.StatusCode = (int)responseMessage.StatusCode;
|
|
134 foreach (var header in responseMessage.Headers)
|
|
135 {
|
|
136 response.Headers[header.Key] = header.Value.ToArray();
|
|
137 }
|
|
138
|
|
139 foreach (var header in responseMessage.Content.Headers)
|
|
140 {
|
|
141 response.Headers[header.Key] = header.Value.ToArray();
|
|
142 }
|
|
143
|
|
144 response.Headers.Remove("transfer-encoding");
|
|
145 }
|
|
146
|
|
147 static async Task WriteResponse(HttpRequest currentReqest, string url, HttpResponseMessage responseMessage, HttpResponse response, bool isAjax)
|
|
148 {
|
|
149 var result = await responseMessage.Content.ReadAsStringAsync();
|
|
150
|
|
151 var ReportServer = url.Contains("/ReportServer/", StringComparison.InvariantCultureIgnoreCase) ? "ReportServer" : "Reports";
|
|
152
|
|
153 var reportUri = new Uri(url);
|
|
154 var proxyUrl = String.Format("{0}://{1}{2}/ssrsproxy/{3}/{4}/{5}", currentReqest.Scheme, currentReqest.Host.Value, currentReqest.PathBase,
|
|
155 reportUri.Scheme, reportUri.Host, reportUri.Port);
|
|
156
|
|
157 if (isAjax && result.IndexOf("|") != -1)
|
|
158 {
|
|
159 var builder = new StringBuilder();
|
|
160
|
|
161 var delimiterIndex = 0;
|
|
162 var length = 0;
|
|
163 var index = 0;
|
|
164
|
|
165 var type = "";
|
|
166 var id = "";
|
|
167 var content = "";
|
|
168
|
|
169 while (index < result.Length)
|
|
170 {
|
|
171 delimiterIndex = result.IndexOf("|", index);
|
|
172 if (delimiterIndex == -1)
|
|
173 {
|
|
174 break;
|
|
175 }
|
|
176 length = int.Parse(result.Substring(index, delimiterIndex - index));
|
|
177 if ((length % 1) != 0)
|
|
178 {
|
|
179 break;
|
|
180 }
|
|
181 index = delimiterIndex + 1;
|
|
182 delimiterIndex = result.IndexOf("|", index);
|
|
183 if (delimiterIndex == -1)
|
|
184 {
|
|
185 break;
|
|
186 }
|
|
187 type = result.Substring(index, delimiterIndex - index);
|
|
188 index = delimiterIndex + 1;
|
|
189 delimiterIndex = result.IndexOf("|", index);
|
|
190 if (delimiterIndex == -1)
|
|
191 {
|
|
192 break;
|
|
193 }
|
|
194 id = result.Substring(index, delimiterIndex - index);
|
|
195 index = delimiterIndex + 1;
|
|
196 if ((index + length) >= result.Length)
|
|
197 {
|
|
198 break;
|
|
199 }
|
|
200 content = result.Substring(index, length);
|
|
201 index += length;
|
|
202 if (result.Substring(index, 1) != "|")
|
|
203 {
|
|
204 break;
|
|
205 }
|
|
206 index++;
|
|
207
|
|
208 content = content.Replace($"/{ReportServer}/", $"{proxyUrl}/{ReportServer}/", StringComparison.InvariantCultureIgnoreCase);
|
|
209 if (content.Contains("./ReportViewer.aspx", StringComparison.InvariantCultureIgnoreCase))
|
|
210 {
|
|
211 content = content.Replace("./ReportViewer.aspx", $"{proxyUrl}/{ReportServer}/Pages/ReportViewer.aspx", StringComparison.InvariantCultureIgnoreCase);
|
|
212 }
|
|
213 else
|
|
214 {
|
|
215 content = content.Replace("ReportViewer.aspx", $"{proxyUrl}/{ReportServer}/Pages/ReportViewer.aspx", StringComparison.InvariantCultureIgnoreCase);
|
|
216 }
|
|
217
|
|
218 builder.Append(String.Format("{0}|{1}|{2}|{3}|", content.Length, type, id, content));
|
|
219 }
|
|
220
|
|
221 result = builder.ToString();
|
|
222 }
|
|
223 else
|
|
224 {
|
|
225 result = result.Replace($"/{ReportServer}/", $"{proxyUrl}/{ReportServer}/", StringComparison.InvariantCultureIgnoreCase);
|
|
226
|
|
227 if (result.Contains("./ReportViewer.aspx", StringComparison.InvariantCultureIgnoreCase))
|
|
228 {
|
|
229 result = result.Replace("./ReportViewer.aspx", $"{proxyUrl}/{ReportServer}/Pages/ReportViewer.aspx", StringComparison.InvariantCultureIgnoreCase);
|
|
230 }
|
|
231 else
|
|
232 {
|
|
233 result = result.Replace("ReportViewer.aspx", $"{proxyUrl}/{ReportServer}/Pages/ReportViewer.aspx", StringComparison.InvariantCultureIgnoreCase);
|
|
234 }
|
|
235 }
|
|
236
|
|
237 response.Headers.Remove("Content-Length");
|
|
238 response.Headers.Append("Content-Length", new string[] { System.Text.Encoding.UTF8.GetByteCount(result).ToString() });
|
|
239
|
|
240 await response.WriteAsync(result);
|
|
241 }
|
|
242 }
|
|
243 }
|