root/lang/csharp/soyText/soyText/DocumentWebServer.cs @ 37387

Revision 37387, 11.2 kB (checked in by hoge1e3, 3 years ago)
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Text.RegularExpressions;
6using System.Net;
7using System.Web;
8using System.Diagnostics;
9using System.IO;
10
11namespace SoyText
12{
13    public class DocumentWebServer
14    {
15        int port;
16        DocumentSet documentSet;
17        public static string detectContentType(Document d)
18        {
19            var c = d.str["Content-Type"];
20            if (c != null) return c;
21            var n = d.str["name"];
22            c = "text/plain; charset=utf-8";
23            if (n != null)
24            {
25                if (n.EndsWith(".js"))
26                {
27                    c = "text/javascript; charset=utf-8";
28                }
29                if (n.EndsWith(".html"))
30                {
31                    c = "text/html; charset=utf-8";
32                }
33            }
34            return c;
35        }
36        void feedDocumentBody(Document d,HttpListenerResponse res) {
37            res.ContentType = detectContentType(d);
38            var lastup = lastModifiedField(d);
39            res.Headers["Last-Modified"] = lastup;
40            Debug.syslog("last up :" + lastup);
41            if (d.str["file"] != null)
42            {
43                try
44                {
45                    Httpd.respondByFile(res, d.str["file"]);
46                }
47                catch (IOException e)
48                {
49                    Httpd.respondByString(res, e.ToString());
50                }
51            }
52            else
53            {
54                Httpd.respondByString(res, d.body);
55            }
56        }
57        string lastModifiedField(Document d)
58        {
59            return TimeFormat.toRFC2822(TimeFormat.toUtcTicks(d.lastUpdate, TimeZone.CurrentTimeZone));
60        }
61        void feedDocumentHead(Document d, HttpListenerResponse res)
62        {
63            var c = "text/plain; charset=utf-8";
64            res.ContentType = c;
65            res.Headers["Last-Modified"] = lastModifiedField(d);
66            Httpd.respondByString(res, d.head);
67        }
68        void feedDocumentHeadBody(Document d, HttpListenerResponse res)
69        {
70            var c = "text/plain; charset=utf-8";
71            res.ContentType = c;
72            res.Headers["Last-Modified"] = lastModifiedField(d);
73            Httpd.respondByString(res, d.content);
74        }
75
76        const string bodyAttr = "_body";
77        void procDocument(Document d, string query, HttpListenerRequest req, HttpListenerResponse res)
78        {
79            if (req.HttpMethod == "GET")
80            {
81                var lm = req.Headers["If-Modified-Since"];
82                if (lm != null)
83                {
84                    var oneSec = 10000000;
85                    //   10^-9 = 0.000000001(10億分の1)
86                    // 100nano = 10^-7 
87                    // 1sec/100nano sec = 1 sec / (10^-7) sec = 10^7
88                    var ifModifiedSince = TimeFormat.fromRFC2822(lm) + oneSec;
89                    var lastModified = TimeFormat.toUtcTicks(d.lastUpdate, TimeZone.CurrentTimeZone);
90                    var now = TimeFormat.utcnow();
91                    Debug.syslog(req.Url +
92                          "  lm: " + TimeFormat.toRFC2822(lastModified)+
93                          " ifm : " + TimeFormat.toRFC2822(ifModifiedSince) +
94                          "  now: " + TimeFormat.toRFC2822(now)
95                    );
96                    if (lastModified <= ifModifiedSince && ifModifiedSince<now )
97                    {
98                        res.StatusCode = 304;
99                        Debug.syslog(req.Url + " not modified");
100                        return;
101                    }
102                }
103                if (query == "meta")
104                {
105                    feedDocumentHead(d, res);
106                }
107                else if (query == "full")
108                {
109                    feedDocumentHeadBody(d, res);
110                }
111                else
112                {
113                    feedDocumentBody(d, res);
114                }
115            }
116            else if (req.HttpMethod == "POST")
117            {
118                /*var b = new byte[req.ContentLength64];
119                req.InputStream.Read(b, 0, b.Length);
120                char[] cs=System.Text.Encoding.UTF8.GetChars(b);
121                var str = new String(cs);
122                */
123                var str = getContentStr(req);
124
125                //str=HttpUtility.UrlDecode(str);
126                var keys=HttpUtility.ParseQueryString(str);
127                var debug = "";
128                foreach (var k in keys.AllKeys)
129                {
130                    debug+=(k + ": " + keys[k]+"\n");
131                    if (k == bodyAttr)
132                    {
133                        d.body = keys[k];
134                    }
135                    else
136                    {
137                        d.str[k] = keys[k];
138                    }
139
140                }
141                d.save();
142                Httpd.respondByString(res, "id: "+d.id+"\n"+debug);
143            }
144        }
145        static string getContentStr(HttpListenerRequest req)
146        {
147            var b = new byte[req.ContentLength64];
148            req.InputStream.Read(b, 0, b.Length);
149            char[] cs = System.Text.Encoding.UTF8.GetChars(b);
150            var str = new String(cs);
151            return str;
152        }
153        public void openInBrowser(Document d) {
154            if (d == null) return;
155            Process.Start("http://localhost:"+port+"/byid/" + d.id);
156        }
157        public DocumentWebServer(DocumentSet documentSet,int port)
158        {
159            this.port = port;
160            this.documentSet = documentSet;
161            new Httpd(port, (req, res) =>
162            {
163                var u = req.Url;
164                var str = u.PathAndQuery;
165                str = HttpUtility.UrlDecode(str,Encoding.UTF8);
166                var pathQuery = Regex.Split(str,@"\?");
167                str = pathQuery[0];
168                var query = "";
169                if (pathQuery.Length > 1)
170                {
171                    query = pathQuery[1];
172                }
173                Debug.syslog("Query = " + str+ "?" +query);
174                //var m=Regex.Match(str,@"byId/");
175                Debug.syslog(str);
176                var s=Regex.Split(str, @"/");
177                if (req.RemoteEndPoint.Address.ToString()!="127.0.0.1" &&
178                    req.RemoteEndPoint.Address.ToString()!="::1")
179                {
180                    res.StatusCode = 403;
181                    Httpd.respondByString(res, "isLocal "+req.IsLocal+" / "+req.RemoteEndPoint.Address);
182                    return;
183                }
184                if (s.Length>=2 && s[1].ToLower()=="byid" )
185                {
186                    var id = s[2];
187                    Debug.print("ID=" + id);
188                    Document d = documentSet.byId(id);
189                    if (d != null)
190                    {
191                        procDocument(d, query, req, res);           
192                    }
193                    else
194                    {
195                        res.StatusCode = 404;
196                        Httpd.respondByString(res,id+" Not found");
197                    }
198                }
199                else if (s.Length >= 3 && s[1].ToLower() == "asyncsearch")
200                {
201                    var se = documentSet.createLoggedDocumentSearcher(s[2]);
202                    se.timeOut = 10000000;
203                    foreach (var dd in se.search()){}
204                    var d=se.searchLog;
205                    feedDocumentHeadBody(d,  res);
206                }
207                else if (req.HttpMethod == "POST" && s.Length >= 2 && s[1].ToLower() == "new")
208                {
209                    var d = documentSet.createDocument();
210                    procDocument(d, query, req, res);
211                }
212                else if (req.HttpMethod == "POST" && s.Length >= 2 && s[1].ToLower() == "getcontents")
213                {
214                    getContents(query, req, res);
215                }
216                else
217                {
218                    //var c = new AndCondition();
219                    var cstr = "";
220                    for (var i = 1; i < s.Length - 1; i++)
221                    {
222                        if (i > 1) cstr += " ";
223                        cstr += "tag:" + s[i];
224                        // c.add(new AttributeCondition("tag",s[i]));
225                    }
226                    var name = s[s.Length - 1];
227                    if (name == "")
228                    {
229                        search(cstr, res);
230                    }
231                    else
232                    {
233                        var nc = new AttributeCondition("name", name);
234                        //c.add();
235                        //var src=documentSet.createDocumentSearcher(c);
236                        Document found = null;
237                        foreach (var d in documentSet.search(cstr, true))
238                        {
239                            if (nc.matches(d))
240                            {
241                                found = d;
242                                break;
243                            }
244                        }
245                        if (found != null)
246                        {
247                            procDocument(found, query, req, res);
248                        }
249                        else
250                        {
251                            res.StatusCode = 404;
252                            Httpd.respondByString(res, "Not found : " + str);
253                        }
254                    }
255                }
256            });
257        }
258
259        private void getContents(string query, HttpListenerRequest req, HttpListenerResponse res)
260        {
261            var str = getContentStr(req);
262            var keys = HttpUtility.ParseQueryString(str);
263            var ids = keys["ids"];
264            //content=HttpUtility.UrlDecode(content);
265            var r=new Random();
266            var sep = "---" + r.Next(1000000) + "----" + r.Next(1000000)+"\n";
267            var buf = "";
268            foreach (var line in Str.lines(ids)) {
269                Debug.syslog("getContents " + line);
270                var d=documentSet.byId(line);
271                if (d==null) continue;
272                buf += sep;
273                if (d.str["id"]!=d.id)
274                {
275                    buf += "id :" + d.id + "\n";
276                }
277                buf += "lastUpdate :" + TimeFormat.format(d.lastUpdate) + "\n";
278                //buf += "\n";
279                buf += d.content;
280                buf += "\n";
281            }
282            buf += sep;
283            Debug.syslog("getContents respond");
284               
285            Httpd.respondByString(res, buf);
286            Debug.syslog("getContents done");
287        }
288
289        private void search(string cstr, HttpListenerResponse res)
290        {
291            var buf = "";
292            foreach (var d in documentSet.search(cstr, true))
293            {
294                buf += "<a href=\"/byid/" + d.id + "\">" + d.ToString() + "</a><br/>\n";
295
296            }
297            res.ContentType = "text/html; charset=utf-8";
298            Httpd.respondByString(res, buf);
299        }
300    }
301}
Note: See TracBrowser for help on using the browser.