// 处理一次请求 private void _request_once(HttpListenerContext ctx) { HttpListenerRequest req = ctx.Request; HttpListenerResponse res = ctx.Response; FawRequest _req = new FawRequest() { _check_int = m_check_int, _check_long = m_check_long, _check_string = m_check_string }; _req.m_url = req.RawUrl; // 此处缺失schema://domain:host _req.m_method = req.HttpMethod.ToUpper(); // 获取请求命令 _req.m_path = req.RawUrl.simplify_path(); int _p = _req.m_path.IndexOfAny(new char [] { '?', '#' }); if (_p > 0) { _req.m_path = _req.m_path.Substring(0, _p); } // 获取请求内容 foreach (string str_key in req.QueryString.AllKeys) { _req.m_gets.Add(str_key, req.QueryString [str_key]); } if (_req.m_method == "POST") { (_req.m_posts, _req.m_files) = parse_form(req); } // 获取请求者IP if ((req.Headers ["X-Real-IP"]?.Length ?? 0) > 0) { _req.m_ip = req.Headers ["X-Real-IP"]; _req.m_agent_ip = req.UserHostAddress; } else { _req.m_ip = req.UserHostAddress; } FawResponse _res = new FawResponse(); try { // 生成请求内容 res.StatusCode = 200; byte [] result_data = new byte [0]; if (_req.m_method != "HEAD") { try { if (_req.m_path.left_is("/api/")) { bool _proc = false; if (m_request_handlers.ContainsKey($"{_req.m_method} {_req.m_path}")) { m_request_handlers [$"{_req.m_method} {_req.m_path}"].process(_req, _res); _proc = true; } else if (m_request_handlers.ContainsKey($" {_req.m_path}")) { m_request_handlers [$" {_req.m_path}"].process(_req, _res); _proc = true; } if (!_proc) { throw new Exception("Unknown request / 未知请求"); } } else if (_req.m_path.left_is("/swagger/") && m_doc_info != null) { if (_req.m_path == "/swagger/api.json") { _res.write(m_swagger_data); _res.set_content_from_filename(_req.m_path); } else { var _asm_path = $"{MethodBase.GetCurrentMethod ().DeclaringType.Namespace}.Swagger.res.{_req.m_path.mid ("/swagger/")}"; using (var _stream = Assembly.GetCallingAssembly().GetManifestResourceStream(_asm_path)) { if (_stream == null) { throw new Exception("File Not Found"); } var _buffer = new byte [_stream.Length]; _stream.Read(_buffer); _res.write(_buffer); _res.set_content_from_filename(_asm_path); } } } else if (_req.m_path.left_is("/monitor/") && m_monitor != null) { if (_req.m_path == "/monitor/data.json") { _res.write(m_monitor.get_json().Result); _res.set_content_from_filename(_req.m_path); } } else if (_req.m_method == "GET") { bool _is_404 = (_req.m_path == "/404.html"); if (_is_404) { _res.m_status_code = 404; } else if (_req.m_path == "/") { if (File.Exists($"{m_wwwroot}index.html")) { _req.m_path = "/index.html"; } else if (File.Exists($"{m_wwwroot}index.htm")) { _req.m_path = "/index.htm"; } } _req.m_path = $"{m_wwwroot}{_req.m_path.Substring (1)}"; if (File.Exists(_req.m_path)) { _res.write_file(_req.m_path); } else if (_is_404) { _res.write("404 Not Found"); } else { _res.redirect("404.html"); } } result_data = _res._get_writes(); res.StatusCode = _res.m_status_code; } catch (KeyNotFoundException ex) { result_data = get_failure_res($"not given parameter {ex.Message.mid ("The given key '", "'")}"); res.StatusCode = 500; } catch (Exception ex) { result_data = get_failure_res(ex.GetType().Name == "Exception" ? ex.Message : ex.ToString()); res.StatusCode = 500; } } // 生成请求头 foreach (var(_key, _value) in _res.m_headers) { res.AppendHeader(_key, _value); } Action <string, string> _unique_add_header = (_key, _value) => { if (!_res.m_headers.ContainsKey(_key)) { res.AppendHeader(_key, _value); } }; // HTTP头输入可以自定 _unique_add_header("Cache-Control", (_req.m_method == "GET" ? "private" : "no-store")); _unique_add_header("Content-Type", "text/plain; charset=utf-8"); _unique_add_header("Server", "Microsoft-IIS/7.5"); // nginx/1.9.12 _unique_add_header("X-Powered-By", "ASP.NET"); _unique_add_header("X-AspNet-Version", "4.0.30319"); _unique_add_header("Access-Control-Allow-Origin", "*"); _unique_add_header("Access-Control-Allow-Headers", "X-Requested-With,Content-Type,Accept"); _unique_add_header("Access-Control-Allow-Methods", "HEAD,GET,POST,PUT,DELETE,OPTIONS"); //_unique_add_header ("Content-Length", ""); // 添加cookie //res.SetCookie (new Cookie ()); // 是否启用压缩 string [] encodings = req.Headers ["Accept-Encoding"]?.Split(',') ?? new string [0]; encodings = (from p in encodings select p.Trim().ToLower()).ToArray(); if (Array.IndexOf(encodings, "gzip") >= 0) { // 使用 gzip 压缩 _unique_add_header("Content-Encoding", "gzip"); _unique_add_header("Vary", "Accept-Encoding"); result_data = result_data.gzip_compress(); } else if (Array.IndexOf(encodings, "deflate") >= 0) { // 使用 deflate 压缩 _unique_add_header("Content-Encoding", "deflate"); _unique_add_header("Vary", "Accept-Encoding"); result_data = result_data.deflate_compress(); } res.OutputStream.Write(result_data, 0, result_data.Length); } catch (Exception ex) { Log.show_error(ex); } finally { res.Close(); } }
public void process(FawRequest _req, FawResponse _res) { var _params = new object [m_params.Count]; bool _ignore_return = false; for (int i = 0; i < m_params.Count; ++i) { if (m_params [i].Item1 != null) { _params [i] = _req.get_type_value(m_params [i].Item1, m_params [i].Item2); } else { switch (m_params [i].Item2) { case "FawRequest": _params [i] = _req; break; case "FawResponse": _params [i] = _res; _ignore_return = true; break; case ":IP": _params [i] = _req.m_ip; break; case ":AgentIP": _params [i] = _req.m_agent_ip; break; default: throw new Exception("Request parameter types that are not currently supported / 暂不支持的Request参数类型"); } } } try { var _ret = m_method.Invoke(null, _params); //if (_ret.GetType () == typeof (Task<>)) // 始终为False if (_ret is Task _t) { if (_ret.GetType() != typeof(Task)) { _ret = _ret.GetType().InvokeMember("Result", BindingFlags.GetProperty, null, _ret, null); } else { _t.Wait(); _ret = null; } } if (!_ignore_return) { if (_ret is byte _byte) { _res.write(_byte); } else if (_ret is byte [] _bytes) { _res.write(_bytes); } else { string _content = (_ret.GetType().IsPrimitive ? _ret.to_str() : _ret.to_json()); object _o; if (_content == "") { _o = new { result = "success" }; } else if (_content[0] != '[' && _content[0] != '{') { _o = new { result = "success", content = _content }; } else { _o = new { result = "success", content = JToken.Parse(_content) }; } _res.write(_o.to_json()); } } } catch (TargetInvocationException ex) { throw ex.InnerException; } }