PageRenderTime 47ms CodeModel.GetById 33ms app.highlight 10ms RepoModel.GetById 2ms app.codeStats 0ms

/src/kilim/http/HttpSession.java

http://github.com/kilim/kilim
Java | 163 lines | 103 code | 12 blank | 48 comment | 8 complexity | df4b7bece1e1b5f5cedbebe82aba686b MD5 | raw file
  1package kilim.http;
  2
  3/* Copyright (c) 2006, Sriram Srinivasan, nqzero 2016
  4 *
  5 * You may distribute this software under the terms of the license 
  6 * specified in the file "License"
  7 */
  8
  9import java.io.EOFException;
 10import java.io.File;
 11import java.io.FileInputStream;
 12import java.io.IOException;
 13import java.io.OutputStream;
 14import java.nio.channels.FileChannel;
 15
 16import kilim.Pausable;
 17import kilim.nio.SessionTask;
 18
 19/**
 20 * Responsible for creating an HTTPRequest object out of raw bytes from a socket, and for sending an HTTPResponse object
 21 * in its entirety.
 22 */
 23public class HttpSession extends SessionTask {
 24
 25    /**
 26     * Reads the socket, parses the HTTP headers and the body (including chunks) into the req object.
 27     * 
 28     * @param req
 29     *            . The HttpRequest object is reset before filling it in.
 30     * @return the supplied request object. This is to encourage buffer reuse.
 31     * @throws IOException
 32     */
 33    public HttpRequest readRequest(HttpRequest req) throws IOException, Pausable {
 34        req.reuse();
 35        req.readFrom(endpoint);
 36        return req;
 37    }
 38
 39    // public static void dumpBuf(String msg, ByteBuffer buffer) {
 40    // System.out.println(msg);
 41    // int pos = buffer.position();
 42    // for (int i = 0; i < pos; i++) {
 43    // System.out.print((char)buffer.get(i));
 44    // }
 45    // System.out.println("============================");
 46    // }
 47
 48    /**
 49     * Send the response object in its entirety, and mark it for reuse. Often, the resp object may only contain the
 50     * header, and the body is sent separately. It is the caller's responsibility to make sure that the body matches the
 51     * header (in terms of encoding, length, chunking etc.)
 52     */
 53    public void sendResponse(HttpResponse resp) throws IOException, Pausable {
 54        resp.writeTo(endpoint);
 55        resp.reuse();
 56    }
 57
 58    static byte[] pre  = "<html><body><p>".getBytes();
 59    static byte[] post = "</body></html>".getBytes();
 60
 61    /**
 62     * Send an error page to the client.
 63     * 
 64     * @param resp The response object. 
 65     * @param statusCode See HttpResponse.ST*  
 66     * @param htmlMsg  The body of the message that gives more detail. 
 67     * @throws IOException
 68     * @throws Pausable
 69     */
 70    public void problem(HttpResponse resp, byte[] statusCode, String htmlMsg) throws IOException, Pausable {
 71        resp.status = statusCode;
 72        resp.setContentType("text/html");
 73        OutputStream os = resp.getOutputStream();
 74        os.write(pre);
 75        os.write(htmlMsg.getBytes());
 76        os.write(post);
 77        sendResponse(resp);
 78    }
 79
 80    /**
 81     * send a file with content length to the client
 82     * @param req the request
 83     * @param resp the response
 84     * @param file the file to send
 85     * @param contentType if non-null, set the content type
 86     * @return 0 on success, 1 for not found, 2 for couldn't send
 87     */
 88    public int sendFile(HttpRequest req,HttpResponse resp,File file,String contentType)
 89            throws Pausable {
 90        FileInputStream fis = null;
 91        FileChannel fc;
 92        boolean headOnly = req.method.equals("HEAD");
 93
 94        try {
 95            fis = new FileInputStream(file);
 96            fc = fis.getChannel();
 97        } catch (IOException ex) {
 98            try { fis.close(); } catch (Exception ex2) {}
 99            return 1;
100        }
101        try {
102            if (contentType != null)
103                resp.setContentType(contentType);
104            resp.setContentLength(file.length());
105            sendResponse(resp);
106            if (!headOnly)
107                endpoint.write(fc, 0, file.length());
108        }
109        catch (IOException ex) {
110            return 2;
111        }
112        finally {
113            try { fc.close(); } catch (Exception ex) {}
114            try { fis.close(); } catch (Exception ex) {}
115        }
116        return 0;
117    }
118    public boolean check(HttpResponse resp,File file,String...bases) throws IOException, Pausable {
119        try {
120            String path = file.getCanonicalPath();
121            for (String base : bases)
122                if (path.startsWith(base))
123                    return true;
124        }
125        catch (Exception ex) {}
126        return false;
127    }
128
129    public interface StringRouter {
130        public String route(HttpRequest req) throws Pausable;
131    }
132    public static class StringSession extends HttpSession {
133        StringRouter handler;
134        public StringSession(StringRouter handler) { this.handler = handler; }
135        public void execute() throws Pausable, Exception {
136            try {
137                // We will reuse the req and resp objects
138                HttpRequest req = new HttpRequest();
139                HttpResponse resp = new HttpResponse();
140                while (true) {
141                    super.readRequest(req);
142                    if (req.keepAlive())
143                        resp.addField("Connection", "Keep-Alive");
144                    OutputStream out = resp.getOutputStream();
145                    String result = handler.route(req);
146                    out.write( result.getBytes() );
147                    sendResponse(resp);
148                    if (!req.keepAlive()) 
149                        break;
150                }
151            }
152            catch (EOFException e) {}
153            catch (IOException ioe) {
154                System.out.println("[" + this.id + "] IO Exception:" + ioe.getMessage());
155            }
156            catch (Exception ex) {
157                System.out.println("HttpSession.Simple:exception -- " + ex);
158                ex.printStackTrace();
159            }
160            super.close();
161        }
162    }
163}