Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

A simple, standardized interface library to Erlang HTTP Servers.

tree: c5e5753cea

Fetching latest commit…

Cannot retrieve the latest commit at this time

README.markdown

SimpleBridge

SimpleBridge takes the pain out of coding to multiple Erlang HTTP servers by creating a standardized interface. It currently supports Mochiweb, Inets, and Misultin, with Yaws coming soon.

SimpleBridge is used in the experimental branch of the The Nitrogen Web Framework.

In a sense, it is similar to EWGI, except SimpleBridge has some key improvements/differences:

  • Smaller code base - SimpleBridge is 870 lines, compared to 1,974 lines for EWGI. This is because SimpleBridge uses the underlying HTTP server's built in parsing functions as much as possible.
  • Easily extended - Takes about 150 lines to add support for a new HTTP server, vs. ~350 for EWGI.
  • MultiPart File Uploads - SimpleBridge has better support for HTTP POSTS, including support for multipart file uploads, with size limits and handle-able errors.
  • Static File Support - Support for sending a static file to the browser, using the underlying HTTP server's own methods.
  • Cookies Support - SimpleBridge provides interface functions for getting and setting cookies.
  • No Middleware Components - SimpleBridge does not explicitly support EWGI's concept of "middleware components". (Though you could probably fake it, haven't tried.)

SimpleBridge is split into two parts:

  • A Request Bridge is a parameterized module that allows you to see information about the incoming request.
  • A Response Bridge is a parameterized module that allows you to construct a response.

Hello World Example

% SimpleBridge Hello World Example in Mochiweb

start(_, _) ->
    Options = [{ip, "127.0.0.1"}, {port, 8000}],
    Loop = fun loop/1,
    mochiweb_http:start([{name, mochiweb_example_app}, {loop, Loop} | Options]).

loop(Req) ->
    Request = simple_bridge:make_request(mochiweb_request_bridge, {Req, "./wwwroot"}),
    HTML = [
        "<h1>Hello, World!</h1>",
        io_lib:format("METHOD: ~p~n<br><br>", [Request:request_method()]),
        io_lib:format("COOKIES: ~p~n<br><br>", [Request:cookies()]),
        io_lib:format("HEADERS: ~p~n<br><br>", [Request:headers()]),
        io_lib:format("QUERY PARAMETERS: ~p~n<br><br>", [Request:query_params()])       
    ],

    Response = simple_bridge:make_response(mochiweb_response_bridge, {Req, "./wwwroot"}),       
    Response1 = Response:status_code(200),
    Response2 = Response1:header("Content-Type", "text/html"),
    Response3 = Response2:data(HTML),
    Response3:build_response().

Request Bridges

How do I make a request bridge?

To make a request bridge for an incoming request, call the simple_bridge:make_request/2 function, specifying the appropriate bridge module for your HTTP server, and the arguments that it needs. This code would sit in the loop/1 function of a Mochiweb server, or the do/1 function of an Inets server.

Inets example:

RequestBridge = simple_bridge:make_request(inets_response_bridge, Info)

Mochiweb example:

RequestBridge = simple_bridge:make_request(mochiweb_response_bridge, [{Req, Docroot}]).

What can I do with the request bridge object?

Once you have created the request bridge object (a parameterized module), it provides you with a standard interface for accessing the request method, path, query parameters, post parameters, headers, and cookies of the request:

Request Bridge Interface

  • Bridge:request_method() - returns 'GET', 'POST', 'HEAD', etc.
  • Bridge:path() - returns the requested path and file.
  • Bridge:peer_ip() - returns the client's IP address in tuple format (74.125.67.100 = {74, 125, 67, 100})
  • Bridge:peer_port() - returns the client's port.
  • Bridge:headers() - returns a proplist of headers, [{header1, "Value1"}, {header2, "Value2"}, ...]
  • Bridge:header(Header) - returns the value of a header.
  • Bridge:cookies() - returns a proplist of cookies, [{"Cookie1", "Value1"}, {"Cookie2", "Value2"}, ...]
  • Bridge:query_params() - returns a proplist of query params, [{"Query1", "Value1"}, {"Query2", "Value2"}, ...]
  • Bridge:post_params() - returns a proplist of post params, [{"Post1", "Value1"}, {"Post2", "Value2"}, ...]
  • Bridge:post_files() - returns a list of upload_file records, describing the files uploaded in a multipart post.
  • Bridge:request_body() - returns the request body that has been read so far, as a list.
  • Bridge:error() - returns an Erlang term describing any errors that happened while parsing a multipart post.

What modules are involved in a request bridge?

  • request_bridge.erl - The behaviour interface that request bridge modules must implement.
  • request_bridge_wrapper.erl - A parameterized module that wraps a request.
  • inets_request_bridge.erl - The request bridge module for Inets.
  • mochiweb_request_bridge.erl - The request bridge module for Mochiweb.
  • ???_request_bridge.erl - Support for more servers on the way.

To extend the SimpleBridge to work with other HTTP servers (or other versions of Inets, Mochiweb, or Yaws), copy and modify inets_request_bridge.erl or mochiweb_request_bridge.erl.

Response Bridges

How do I make a response bridge?

To make a request bridge for an incoming request, call the simple_bridge:make_response/2 function, specifying the appropriate bridge module for your HTTP server, and the arguments that it needs. This code would sit in the loop/1 function of a Mochiweb server, or the do/1 function of an Inets server.

Inets example:

ResponseBridge = simple_bridge:make_response(inets_response_bridge, Info)

Mochiweb example:

ResponseBridge = simple_bridge:make_response(mochiweb_response_bridge, {Req, Docroot})

What can I do with the Response Bridge?

Once you have created the request bridge object (a parameterized module), it provides you with a standard interface for combining headers, cookies, and a response body into a response appropriate for your http server.

Each function below returns a new bridge object, so your will need to chain together requests like this:

Bridge = simple_bridge:make_response(inets_response_bridge, Info),
Bridge1 = Bridge:status_code(200),
Bridge2 = Bridge1:header("Header1", "Value1"),
Bridge3 = Bridge2:data(HTML),
etc.

Response Bridge Interface

  • Bridge:status_code(Code) - set the HTTP status code. (200, 404, etc.)
  • Bridge:header(Name, Value) - set an HTTP header.
  • Bridge:clear_headers() - clear all previously set headers.
  • Bridge:cookie(Name, Value) - set a cookie for path "/" with expiration in 20 minutes.
  • Bridge:cookie(Name, Value, Path, Exp) - Set a cookie. Exp is an integer in minutes.
  • Bridge:clear_cookies() - clear all previously set cookies.
  • Bridge:data(Data) - set the data to return in the response. Usually HTML goes here.
  • Bridge:file(File) - Send a static file to the browser.

Finally, you build the response to send to your HTTP server with the build_response/0 function.

  • Bridge:build_response() - Create a response tuple that you can hand off to your HTTP server.

What modules are involved in a response bridge?

  • response_bridge.erl - The behaviour interface that response bridge modules must implement.
  • response_bridge_wrapper.erl - A parameterized module that wraps a response.
  • inets_response_bridge.erl - The response bridge module for Inets.
  • mochiweb_response_bridge.erl - The response bridge module for Mochiweb.
  • ???_response_bridge.erl - Support for more servers on the way.

To extend the SimpleBridge to other HTTP servers (or other versions of Inets, Mochiweb, or Yaws), copy and modify inets_response_bridge.erl or mochiweb_response_bridge.erl.

Something went wrong with that request. Please try again.