/**
   * Override this to customize the server.
   *
   * <p>
   *
   * <p>(By default, this delegates to serveFile() and allows directory listing.)
   *
   * @param session The HTTP session
   * @return HTTP response, see class Response for details
   */
  public Response serve(IHTTPSession session) {
    Map<String, String> files = new HashMap<String, String>();
    Method method = session.getMethod();
    if (Method.PUT.equals(method) || Method.POST.equals(method)) {
      try {
        session.parseBody(files);
      } catch (IOException ioe) {
        return new Response(
            Response.Status.INTERNAL_ERROR,
            MIME_PLAINTEXT,
            "SERVER INTERNAL ERROR: IOException: " + ioe.getMessage());
      } catch (ResponseException re) {
        return new Response(re.getStatus(), MIME_PLAINTEXT, re.getMessage());
      }
    }

    Map<String, String> parms = session.getParms();
    parms.put(QUERY_STRING_PARAMETER, session.getQueryParameterString());
    return serve(session.getUri(), method, session.getHeaders(), parms, files);
  }
    @Override
    public void execute() throws IOException {
      try {
        // Read the first 8192 bytes.
        // The full header should fit in here.
        // Apache's default header limit is 8KB.
        // Do NOT assume that a single read will get the entire header
        // at once!
        byte[] buf = new byte[BUFSIZE];
        splitbyte = 0;
        rlen = 0;
        {
          int read = -1;
          try {
            read = inputStream.read(buf, 0, BUFSIZE);
          } catch (Exception e) {
            safeClose(inputStream);
            safeClose(outputStream);
            throw new SocketException("NanoHttpd Shutdown");
          }
          if (read == -1) {
            // socket was been closed
            safeClose(inputStream);
            safeClose(outputStream);
            throw new SocketException("NanoHttpd Shutdown");
          }
          while (read > 0) {
            rlen += read;
            splitbyte = findHeaderEnd(buf, rlen);
            if (splitbyte > 0) break;
            read = inputStream.read(buf, rlen, BUFSIZE - rlen);
          }
        }

        if (splitbyte < rlen) {
          inputStream.unread(buf, splitbyte, rlen - splitbyte);
        }

        parms = new HashMap<String, String>();
        if (null == headers) {
          headers = new HashMap<String, String>();
        }

        // Create a BufferedReader for parsing the header.
        BufferedReader hin =
            new BufferedReader(new InputStreamReader(new ByteArrayInputStream(buf, 0, rlen)));

        // Decode the header into parms and header java properties
        Map<String, String> pre = new HashMap<String, String>();
        decodeHeader(hin, pre, parms, headers);

        method = Method.lookup(pre.get("method"));
        if (method == null) {
          throw new ResponseException(Response.Status.BAD_REQUEST, "BAD REQUEST: Syntax error.");
        }

        uri = pre.get("uri");

        cookies = new CookieHandler(headers);

        // Ok, now do the serve()
        Response r = serve(this);
        if (r == null) {
          throw new ResponseException(
              Response.Status.INTERNAL_ERROR,
              "SERVER INTERNAL ERROR: Serve() returned a null response.");
        } else {
          cookies.unloadQueue(r);
          r.setRequestMethod(method);
          r.send(outputStream);
        }
      } catch (SocketException e) {
        // throw it out to close socket object (finalAccept)
        throw e;
      } catch (SocketTimeoutException ste) {
        throw ste;
      } catch (IOException ioe) {
        Response r =
            new Response(
                Response.Status.INTERNAL_ERROR,
                MIME_PLAINTEXT,
                "SERVER INTERNAL ERROR: IOException: " + ioe.getMessage());
        r.send(outputStream);
        safeClose(outputStream);
      } catch (ResponseException re) {
        Response r = new Response(re.getStatus(), MIME_PLAINTEXT, re.getMessage());
        r.send(outputStream);
        safeClose(outputStream);
      } finally {
        tempFileManager.clear();
      }
    }