private void Main2(ArgsReader ar) { if (ar.ArgIs("/BEFORE-DL")) { BeforeDLIntervent.Perform(); return; } if (ar.ArgIs("/DISK-YELLOW")) { #if true throw new Exception("廃止"); #else // del @ 2020.4.1 foreach (IService service in new ServiceDistributor().GetAllService()) { service.DiskYellow(); } return; #endif } if (ar.HasArgs()) { throw new Exception("不明なコマンド引数"); } JsonTools.DecodeStringFilter = v => JString.ToJString(v, true, true, true, true); JsonTools.DecodeNestingLevelMax = 30; JsonTools.DecodeObjectCountMax = 1000; HTTPRequest.I = new HTTPRequest(); HTTPRequest.I.IP = File.ReadAllLines("IP.httdat", Encoding.ASCII)[0]; // 正規化済み @ Post2 HTTPRequest.I.Method = File.ReadAllLines("Method.htt2dat", Encoding.ASCII)[0]; // 正規化済み @ Post2 HTTPRequest.I.URLPath = File.ReadAllLines("Path.htt2dat", Encoding.ASCII)[0]; // 正規化済み @ Post2 HTTPRequest.I.HTTP_Version = File.ReadAllLines("HTTP_Version.htt2dat", Encoding.ASCII)[0]; // 正規化済み @ Post2 ProcMain.WriteLog("IP: " + HTTPRequest.I.IP); ProcMain.WriteLog("Method: " + HTTPRequest.I.Method); ProcMain.WriteLog("URLPath: " + HTTPRequest.I.URLPath); ProcMain.WriteLog("HTTP_Version: " + HTTPRequest.I.HTTP_Version); ParsePathQuery(); { string[] keys = File.ReadAllLines("HeaderKeys.htt2dat", Encoding.ASCII); // 正規化済み @ Post2 string[] values = File.ReadAllLines("HeaderValues.htt2dat", Encoding.ASCII); // 正規化済み @ Post2 if (keys.Length != values.Length) { throw null; // 想定外 } for (int index = 0; index < keys.Length; index++) { string key = keys[index]; string value = values[index]; ProcMain.WriteLog("Header: " + key + " ⇒ " + value); HTTPRequest.I.HeaderPairs.Add(key, value); } } { byte[] body = File.ReadAllBytes("Body.htt2dat"); string serviceName = HTTPRequest.I.Query["sn"]; IService service = new ServiceDistributor().GetService(serviceName); object prm = JsonTools.Decode(body); string sPrm = JsonTools.Encode(prm); if (600 < sPrm.Length) { sPrm = sPrm.Substring(0, 500) + "...(省略)"; // 長すぎると表示に時間が掛かるので、 } ProcMain.WriteLog("prm: " + sPrm); try { object ret = service.Perform(prm); string sRet = JsonTools.Encode(ObjectTree.Conv(ret)); ProcMain.WriteLog("ret: " + sRet); byte[] resBody = Encoding.UTF8.GetBytes(sRet); File.WriteAllBytes("ResBody.htt2dat", resBody); File.WriteAllLines("ResHeader.htt2dat", new string[] { "Content-Type: application/json", }); } catch (Exception e) { ProcMain.WriteLog(e); File.WriteAllText("ResHeaderFirstLine.htt2dat", "HTTP/1.1 400 Or 500\r\n", Encoding.ASCII); } } }
public void Main(ArgsReader ar) { int portNo = 80; DocRoot docRoot = new DocRoot(); MIMEType mimeType = new MIMEType(); if (ar.HasArgs()) portNo = int.Parse(ar.NextArg()); portNo = IntTools.ToRange(portNo, 1, 65535); while (ar.HasArgs()) docRoot.AddRootDir(ar.NextArg()); HTTPServerChannel.RequestTimeoutMillis = 30000; // 30 sec HTTPServerChannel.ResponseTimeoutMillis = 2 * 86400000; // 2 day //HTTPServerChannel.FirstLineTimeoutMillis = 2000; // 2 sec == def HTTPServerChannel.IdleTimeoutMillis = 10000; // 10 sec HTTPServerChannel.BodySizeMax = 2000000; // 2 MB HTTPServerChannel.BuffSize = 500000; // 500 KB JsonTools.DecodeStringFilter = v => JString.ToJString(v, true, true, true, true); JsonTools.DecodeNestingLevelMax = 30; JsonTools.DecodeObjectCountMax = 1000; HTTPServer hs = new HTTPServer() { PortNo = portNo, //Backlog = 100, // == def //ConnectMax = 30, // == def Interlude = () => { return Console.KeyAvailable == false; }, HTTPConnected = channel => { string method = channel.Method; string path = channel.Path; HTTPRequest hr = new HTTPRequest(); hr.IP = channel.Channel.Handler.RemoteEndPoint.ToString(); // TODO hr.Method = JString.ToJString(channel.Method, false, false, false, false); // 正規化 hr.URLPath = JString.ToJString(channel.Path, true, false, false, true); // 正規化 // HACK ??? ParsePathQuery より前に DecodeURL しているのでクエリに '?', '&', '=' を使えない??? ParsePathQuery(hr); // 特別な処理:アスタリスクの直前までをパスと見なす。 { int i = hr.Path.IndexOf('*'); if (i != -1) hr.Path = hr.Path.Substring(0, i); } if (hr.Path[hr.Path.Length - 1] == '/') hr.Path += "index.html"; hr.Path = CommonUtils.GetFairRelPath(hr.Path); hr.HTTP_Version = JString.ToJString(channel.HTTPVersion, false, false, false, false); // 正規化 foreach (string[] headerPair in channel.HeaderPairs) { hr.HeaderPairs.Add( JString.ToJString(headerPair[0], true, false, false, true), // 正規化 JString.ToJString(headerPair[1], true, false, false, true) // 正規化 ); } if (hr.Method == "GET") { hr.Json = null; } else if (method == "POST") { hr.Json = JsonTools.Decode(channel.Body); // 正規化 } else { throw new Exception("不明なメソッド"); } // HACK ??? フォルダの場合の 301 対応 string targetFile = docRoot.GetRootDirs().Select(v => Path.Combine(v, hr.Path)).FirstOrDefault(v => File.Exists(v)); if (targetFile == null) { channel.ResStatus = 404; } else { if (StringTools.EndsWithIgnoreCase(targetFile, ".alt.txt")) { string intervateClassName = File.ReadAllLines(targetFile, Encoding.ASCII)[0]; Type intervateClass = Type.GetType(intervateClassName + "," + Assembly.GetEntryAssembly().GetName().Name); ReflectTools.MethodUnit intervateCtor = ReflectTools.GetConstructor(intervateClass); IService service = (IService)intervateCtor.Construct(new object[0]); object ret = service.Perform(hr, ref targetFile); if (ret != null) { string sRet = JsonTools.Encode(ObjectTree.Conv(ret)); byte[] resBody = Encoding.UTF8.GetBytes(sRet); channel.ResStatus = 200; channel.ResBody_B = resBody; channel.ResContentType = "application/json"; goto endSetResponse; } } channel.ResStatus = 200; if (new FileInfo(targetFile).Length <= 2000000) channel.ResBody_B = File.ReadAllBytes(targetFile); else channel.ResBody = ResponseFileReader(targetFile); channel.ResContentType = mimeType.FileToContentType(targetFile); endSetResponse: ; } }, }; ProcMain.WriteLog("Server Started"); hs.Perform(); ProcMain.WriteLog("Server Ended"); }