Home > Tags > HTTP

HTTP

HttpServletRequestWrapperを使って、HTTPリクエストを改変する

OpenAMは、認証済のユーザー情報をHTTPリクエストヘッダーに載せてくれるんですが、Servletでそれってどうやって実現してるのかなーと思って、調べたら HttpServletRequestWrapper クラスを使うようです。

使い方ですが、HttpServletRequestWrapper は、HttpServletRequestインタフェースを実装しているので、HttpServletRequestインタフェースのメソッドをオーバーライドして独自の実装を定義します。
http://mergedoc.sourceforge.jp/tomcat-servletapi-5-ja/javax/servlet/http/HttpServletRequestWrapper.html

今は、すべてのリクエストのヘッダーに情報を付与しようとしているので、getHeader辺りをオーバーライドします。

package org.sample;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

public class HeaderAddedHttpServletRequest extends HttpServletRequestWrapper {

    private Map<String, String> addHeaders;

    public HeaderAddedHttpServletRequest(HttpServletRequest request, Map<String, String> addHeaders) {
        super(request);

        if (addHeaders == null) {
            this.addHeaders = new HashMap<String, String>();
        } else {
            this.addHeaders = addHeaders;
        }
    }

    @Override
    public String getHeader(String name) {
        String header = super.getHeader(name);
        if (header != null) {
            return header;
        }

        header = addHeaders.get(name);
        if (header != null) {
            return header;
        }

        return null;
    }

    @Override
    public Enumeration<String> getHeaderNames() {
        List<String> newHeaderNames = new ArrayList<String>();

        Enumeration<String> currentHeaderNames = super.getHeaderNames();
        while (currentHeaderNames.hasMoreElements()) {
            newHeaderNames.add(currentHeaderNames.nextElement());
        }

        for (Entry<String, String> e : addHeaders.entrySet()) {
            newHeaderNames.add(e.getKey());
        }

        return Collections.enumeration(newHeaderNames);
    }
}

で、すべてのリクエストがこのWrapperクラスを使うようにFilterを定義します。

package org.sample;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;

@WebFilter("/*")
public class AddHeaderFilter implements Filter {

    @Override
    public void init(FilterConfig fConfig) throws ServletException {
    }

    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        Map<String, String> addHeaders = new HashMap<String, String>();
        addHeaders.put("X-USER-ID", "HIJIKATA");
        addHeaders.put("X-USER-NAME", "土方歳三");

        chain.doFilter(new HeaderAddedHttpServletRequest((HttpServletRequest) request, addHeaders), response);
    }
}

これで、HTTPリクエストが飛んできたら自動でヘッダーが付与サれてます。

package org.sample;

import java.io.IOException;
import java.util.Enumeration;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/SampleServlet")
public class SampleServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            String headerValue = request.getHeader(headerName);

            System.out.println(headerName + "=" + headerValue);
        }
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
    }
}
host=localhost:8080
connection=keep-alive
user-agent=Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.152 Safari/535.19
accept=text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
accept-encoding=gzip,deflate,sdch
accept-language=ja,en-US;q=0.8,en;q=0.6
accept-charset=Shift_JIS,utf-8;q=0.7,*;q=0.3
X-USER-ID=HIJIKATA
X-USER-NAME=土方歳三

同様の事はレスポンスでもできます。

シンプルな HTTP Server 書いた

以前の記事の続きということで、シンプルな HTTP Server を書いた。

classファイル一つで動くというお手軽サーバー。マルチスレッド?自分しか使わないからいいんですよ。
お手軽に使いたいのでデフォルトパッケージ。

java SimpleHttpServer "C:\htdocs" 81
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

public class SimpleHttpServer {

    private static String requestPath;

    private static Map<String, String> CONTENT_TYPES = new HashMap<String, String>();

    static {
        CONTENT_TYPES.put("html", "text/html");
        CONTENT_TYPES.put("htm", "text/html");
        CONTENT_TYPES.put("css", "text/css");
        CONTENT_TYPES.put("js", "text/javascript");
        CONTENT_TYPES.put("jpg", "image/jpeg");
        CONTENT_TYPES.put("jpeg", "image/jpeg");
        CONTENT_TYPES.put("png", "image/png");
        CONTENT_TYPES.put("gif", "image/gif");
        CONTENT_TYPES.put("pdf", "application/pdf");
        CONTENT_TYPES.put("txt", "text/plain");
        CONTENT_TYPES.put("xml", "text/xml");
        CONTENT_TYPES.put("zip", "application/zip");
        CONTENT_TYPES.put("exe", "application/octet-stream");
    }

    public static void main(String[] args) throws IOException {
        String documentRoot = args[0];
        int port = Integer.parseInt(args[1]);

        ServerSocket server = new ServerSocket(port);

        while (true) {
            Socket client = server.accept();

            // HTTPリクエストを出力
            outputRequest(client);

            // HTTPレスポンスを出力
            outputResponse(client, documentRoot);
        }
    }

    private static void outputRequest(Socket client) throws IOException {
        System.out.println("------------------------------------------");

        BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));

        // 1行目からリクエストパスを取得しておく(/でアクセスされた場合はindex.htmlを表示)
        String inline = br.readLine();
        requestPath = inline.split(" ")[1];
        if (requestPath.endsWith("/")) {
            requestPath += "index.html";
        }

        while (br.ready() && inline != null) {
            System.out.println(inline);
            inline = br.readLine();
        }

        System.out.println("------------------------------------------");
    }

    private static void outputResponse(Socket client, String documentRoot) throws IOException {
        PrintStream ps = new PrintStream(client.getOutputStream());

        String responseFile = documentRoot + requestPath;
        File file = new File(responseFile);

        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);

            // ヘッダー出力
            int bodyLength = (int) file.length();
            ps.println("HTTP/1.1 200 OK");
            ps.println("Content-Length: " + bodyLength);
            ps.println("Content-Type: " + getContentType(file));
            ps.println("");

            // ボディ出力
            byte buf[] = new byte[bodyLength];

            fis.read(buf);
            ps.write(buf, 0, bodyLength);
            ps.flush();
        } catch (FileNotFoundException e) {
            // ヘッダー出力
            ps.println("HTTP/1.1 404 Not Found");
            ps.println("");
            ps.println("<h1>指定されたファイルは存在しません。</h1>");
        } finally {
            if (fis != null) {
                fis.close();
            }
        }

        ps.close();
    }

    private static String getContentType(File file) {
        String extension = getExtension(file);

        String contentType = CONTENT_TYPES.get(extension);

        if (contentType == null) {
            return "text/html";
        } else {
            return contentType;
        }
    }

    private static String getExtension(File file) {
        String path = file.getPath();
        int lastDotPosition = path.lastIndexOf(".");

        String extension = null;
        if (lastDotPosition == -1) {
            extension = "";
        } else {
            extension = path.substring(lastDotPosition + 1).toLowerCase();
        }

        return extension;
    }
}

コードはGistにもペタリ。
https://gist.github.com/2260004

JavaのHttpClient 4 を触ってみた。

  • Posted by: sinsengumi
  • 2010年10月7日 11:30 AM
  • Java
  • |

HttpClientの3.0系はレガシーということで、4系を触ってみました。
実行環境は以下です。

  • JRE 1.6
  • HttpClient 4.0.3 (httpclient-4.0.3.jar)
  • HttpCore 4.0.1 (httpcore-4.0.1.jar)
  • Commons Logging 1.1.1 (commons-logging-1.1.1.jar)

簡単に、HTTP接続ができていい感じです。

サンプルは以下。

public class HTTPSample {

    private static HttpClient httpClient = new DefaultHttpClient();

    public static void main(String[] args) {

        // プロキシがある場合は、以下のようにして設定する
        //HttpHost proxy = new HttpHost("XXX.XXX.XXX.XXX", 8080);
        //httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);

        Map<String, String> requestParams = new HashMap<String, String>();
        requestParams.put("pattern", "ltrim");
        requestParams.put("lang", "ja");

        httpGet("http://jp2.php.net/manual-lookup.php", requestParams);
        // httpPost("http://jp2.php.net/manual-lookup.php", requestParams);

        // HTTP接続を閉じる(shutdownを実行するとセッションが切れます)
        httpClient.getConnectionManager().shutdown();
    }

    private static void httpGet(String url, Map<String, String> requestParams) {

        HttpGet httpGet = null;

        try {
            // リクエストパラメータの設定
            StringBuilder builder = new StringBuilder(url);
            builder.append("?");
            for (Map.Entry<String, String> entry : requestParams.entrySet()) {
                builder.append((String) entry.getKey());
                builder.append("=");
                builder.append((String) entry.getValue());
                builder.append("&");
            }

            String tmpUrl = builder.toString();
            tmpUrl = tmpUrl.substring(0, tmpUrl.length() - 1);

            httpGet = new HttpGet(tmpUrl);

            System.out.println("executing request " + httpGet.getURI());
            System.out.println("-------------------------------------");

            HttpResponse response = httpClient.execute(httpGet);

            // レスポンスヘッダーの取得
            System.out.println(response.getStatusLine().getStatusCode());

            Header[] headers = response.getAllHeaders();
            for (Header header : headers) {
                System.out.println(header.getName() + ": " + header.getValue());
            }

            System.out.print(System.getProperty("line.separator"));

            // レスポンスボディの取得
            HttpEntity httpEntity = response.getEntity();
            System.out.println(EntityUtils.toString(httpEntity));

        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (httpGet != null) {
                httpGet.abort();
            }
        }
    }

    private static void httpPost(String url, Map<String, String> requestParams) {

        HttpPost httpPost = null;

        try {
            // リクエストパラメータの設定
            List<NameValuePair> params = new ArrayList<NameValuePair>();
            for (Map.Entry<String, String> entry : requestParams.entrySet()) {
                params.add(new BasicNameValuePair((String) entry.getKey(), (String) entry.getValue()));
            }

            httpPost = new HttpPost(url);
            httpPost.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));

            System.out.println("executing request " + httpPost.getURI());
            System.out.println("-------------------------------------");

            // レスポンスヘッダーの取得
            HttpResponse response = httpClient.execute(httpPost);
            System.out.println(response.getStatusLine().getStatusCode());

            Header[] headers = response.getAllHeaders();
            for (Header header : headers) {
                System.out.println(header.getName() + ": " + header.getValue());
            }

            System.out.print(System.getProperty("line.separator"));

            // レスポンスボディの取得
            HttpEntity httpEntity = response.getEntity();
            System.out.println(EntityUtils.toString(httpEntity));

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (httpPost != null) {
                httpPost.abort();
            }
        }
    }
}

参考

Home > Tags > HTTP

Search
Feeds
Meta

Return to page top