// ** This class was generated with DemFGen (vers:11/17/2009) namespace edu.neu.ccs.demeterf.http.classes{ using edu.neu.ccs.demeterf.lib; using System.Net.Sockets; using System.Text; using System.IO; using System; /** Representation of HTTPReq */ public class HTTPReq{ protected readonly HTTPHead head; protected readonly List keys; protected readonly ident body; /** Construct a(n) HTTPReq Instance */ public HTTPReq(HTTPHead head, List keys, ident body){ this.head = head; this.keys = keys; this.body = body; } /** Is the given object Equal to this HTTPReq? */ public override bool Equals(Object o){ if(!(o is HTTPReq))return false; if(o == this)return true; HTTPReq oo = (HTTPReq)o; return (head.Equals(oo.head))&&(keys.Equals(oo.keys))&&(body.Equals(oo.body)); } /** Field Class for HTTPReq.head */ public class headF : edu.neu.ccs.demeterf.Fields.any{} /** Field Class for HTTPReq.keys */ public class keysF : edu.neu.ccs.demeterf.Fields.any{} /** Field Class for HTTPReq.body */ public class bodyF : edu.neu.ccs.demeterf.Fields.any{} /** Default Socket connection timeout (20 seconds) */ public static readonly int DEFAULT_CONN_TIMEOUT = 20*1000; /** Default Socket Response timeout (1 second) */ public static readonly int DEFAULT_RESP_TIMEOUT = 1000; /** Create an HTTP Request with a given Header, MessageHeaders, and Body */ public static HTTPReq create(HTTPHead req, List hds, String body){ return createNoLen(req, hds.append(new MsgHead("Content-Length",""+body.Length)), body); } /** Create an HTTP Request with a given Header, MessageHeaders, and Body */ private static HTTPReq createNoLen(HTTPHead req, List hds, String body){ return new HTTPReq(req, hds, new ident(body)); } /** Create an HTTP Get Request for the given (relative) URL. Then use * {@link #send(String,int) Send} for a Request/Response pair. */ public static HTTPReq Get(String url) { return create(HTTPHead.Get(URL.Parse(url)), List.create(), ""); } /** Create an HTTP Get Request for the given relative URL, to be sent to the * given Host. Use this method for raw Socket/Connection sends, but use * {@link #send(String,int) Send} for a Request/Response pair. */ public static HTTPReq Get(String url, String host) { return create(HTTPHead.Get(URL.Parse(url)), hostHeader(host), ""); } /** Create an HTTP Head Request for the given (relative) URL. Then use * {@link #send(String,int) Send} for a Request/Response pair. */ public static HTTPReq Head(String url) { return create(HTTPHead.Get(URL.Parse(url)), List.create(), ""); } /** Create an HTTP Head Request for the given relative URL, to be sent to the * given Host. Use this method for raw Socket/Connection sends, but use * {@link #send(String,int) Send} for a Request/Response pair. */ public static HTTPReq Head(String url, String host) { return create(HTTPHead.Head(URL.Parse(url)), hostHeader(host), ""); } /** Create an HTTP Post Request to the given (relative) URL. Then use * {@link #send(String,int) Send} for a Request/Response pair. */ public static HTTPReq Post(String url, String body) { return create(HTTPHead.Post(URL.Parse(url)), List.create(), body); } /** Create an HTTP Post Request to the given relative URL, to be sent to the * given Host. Use this method for raw Socket/Connection sends, but use * {@link #send(String,int) Send} for a Request Response Pair. */ public static HTTPReq Post(String url, String host, String body) { return create(HTTPHead.Post(URL.Parse(url)), hostHeader(host), body); } private static List hostHeader(String h) { return List.create(new MsgHead(new ident("Host"), new ident(h))); } /** Add the given Message Headers to this Request */ private HTTPReq addHeaders(List hs){ return createNoLen(head,hs.append(keys),""+body); } /** Add a given Message Headers to this Request */ public HTTPReq addHeader(String key, String val){ return createNoLen(head,keys.append(new MsgHead(key,val)),""+body); } /** Request Types */ public enum ReqType{ GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT, OPTIONS, OTHER }; /** Return this Request's type */ public ReqType getType(){ return head.getType(); } /** Return the URL arguments (key/value) for this request. The URL arguments * follow the base URL after a '?'. * E.g.: /foo/bar?bazzle=13&wizwoz='hello' */ public Map urlArgs(){ return head.GetUrl().urlArgs(); } /** Return the Body arguments (key/value) from this request. The Body arguments * are on a single line of the body, like URLArgs, but without the '?' */ public Map bodyArgs(){ return splitArgs(""+body); } /** Return the relative URL, without any URL arguments */ public String trimmedUrl(){ return head.GetUrl().trimArgs(); } /** Send this Request to the given Server/Port, and return its Response */ public HTTPResp send(String server, int port){ return send(server,port,0); } /** Send this Request to the given Server/Port, and return its Response with * the given response timeout. If the server does not respond in the given * time an */ public HTTPResp send(String server, int port, int respTimeout){ return send(server,port,HTTPReq.DEFAULT_CONN_TIMEOUT, respTimeout); } /** Send this Request to the given Server/Port, and return its * Response, but only wait for the specified timout (in Milliseconds) */ public HTTPResp send(String server, int port, int connTimeout, int respTimeout) { Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // Connect System.Net.IPHostEntry host = System.Net.Dns.GetHostEntry(server); sock.Connect(new System.Net.IPEndPoint(host.AddressList[0], port)); // Add the header and Send addHeaders(hostHeader(server+":"+port)).toSocket(sock); // Read the Response HTTPResp res = HTTPResp.fromSocket(sock); sock.Close(); return res; } /** Write this Request to the given Socket */ public void toSocket(Socket s){ try{ StreamWriter outt = new StreamWriter(new NetworkStream(s)); outt.Write(this.ToString()); outt.Flush(); s.Shutdown(SocketShutdown.Send); }catch(Exception e){ throw e; } } /** Read a request from a Socket, timeout if needed */ public static HTTPReq fromSocket(Socket s){ return fromSocket(s,0); } /** Read a request from a Socket */ public static HTTPReq fromSocket(Socket s, long timeout){ try{ // Recieve Timer //s.ReceiveTimeout = HTTPReq.DEFAULT_RESP_TIMEOUT; s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, HTTPReq.DEFAULT_RESP_TIMEOUT); HTTPReq req = fromInputStream(new NetworkStream(s),timeout); s.Shutdown(SocketShutdown.Receive); return req; }catch(Exception e){ throw e; } } /** Read a Request from an InputStream */ private static HTTPReq fromInputStream(Stream inpt){ return fromInputStream(inpt,0); } /** Read a Request from an InputStream */ public static HTTPReq fromInputStream(Stream inpt, long timeout){ try{ StreamReader inn = new StreamReader(inpt); String first = readLine(inn,timeout); if(first == null)throw new Exception("Empty HTTP Header"); HTTPHead h = HTTPHead.Parse(first); return new HTTPReq(h, ParseMsgHeads(inn,timeout), ParseBody(inn,timeout)); }catch(Exception e){ throw e; } } /** Parse a List of Message Headers */ public static List ParseMsgHeads(StreamReader inn, long timeout){ String line = null; if((line = inn.ReadLine()) == null || line.Length == 0) return List.create(); int colon = line.IndexOf(":"); return ParseMsgHeads(inn,timeout) .push(new MsgHead(new ident(line.Substring(0,colon)), new ident(line.Substring(colon+2)))); } /** Read a single Line */ public static String readLine(StreamReader inn, long timeout){ long start = millis(); String line = ""; while(true){ line = null; try{ line = inn.ReadLine(); return line; }catch(IOException e){ if(timeout > 0 && (millis()-start) > timeout) throw e; } } } static long millis(){ return System.DateTime.Now.Ticks/10000; } /** Parse the Body of a Request */ public static ident ParseBody(StreamReader inn, long timeout){ long start = millis(); StringBuilder sb = new StringBuilder(); char[] buff = new char[1024]; int many = 0; if(!inn.EndOfStream) do{ many = 0; try{ many = inn.Read(buff,0,1024); if(many>0) sb.Append(buff,0,many); }catch(IOException e){ if(timeout > 0 && (millis()-start) > timeout) throw e; } }while(!inn.EndOfStream || many > 0); return new ident(sb.ToString()); } /** Return the Body of this Request */ public String getBodyString(){ return ""+body; } /** Return the Headers of this Request as a Map */ public Map getHeaders(){ return getHeaders(keys); } class HeadFold : List.Fold>{ public override Map fold(MsgHead h, Map m){ return m.put(""+h.GetKey(),""+h.GetValue()); } } /** Return the Headers of this Request as a Map */ public static Map getHeaders(List hds){ return hds.fold(new HeadFold(), Map.create()); } class SplitFold : List.Fold>{ public override Map fold(String p, Map m){ String[] kv = p.Split('='); if(kv.Length < 2)return m; return m.put(kv[0],kv[1]); } } /** Split an argument String into key/value Map */ public static Map splitArgs(String s){ return List.create(s.Split('&')).fold(new SplitFold(), Map.create()); } /** Decode an encoded URL */ public static String decodeURL(String url){ return Uri.UnescapeDataString(url); } /** Encode a (possibly special) URL */ public static String encodeURL(String url){ return Uri.EscapeDataString(url); } /** DGP method from Class PrintToString */ public override String ToString(){ return global::edu.neu.ccs.demeterf.http.classes.PrintToString.PrintToStringM(this); } /** Getter for field HTTPReq.body */ public ident GetBody(){ return body; } /** Getter for field HTTPReq.keys */ public List GetKeys(){ return keys; } /** Getter for field HTTPReq.head */ public HTTPHead GetHead(){ return head; } } }