2010-02-05 9 views
29

Utilizando la instalación predeterminada de Erlang, ¿cuál es el código mínimo necesario para producir un servidor web productor de "Hello World"?¿Cómo escribir un servidor web simple en Erlang?

+0

Como esto es diferente de http://stackoverflow.com/questions/2084639/sinatra-style-web-framework-for-erlang? – Zed

+1

@Zed, Zubair está pidiendo un servidor "hello world" mínimo: tiene una sola "página" porque es mínima. La pregunta a la que se ha vinculado pregunta cómo hacer una aplicación web funcional (de una página, pero responde a una variedad de solicitudes de diferentes maneras). Supongo que este último será ajax-y. – apollodude217

Respuesta

49

Tomando "producir" literalmente, aquí hay uno bastante pequeño. Ni siquiera lee la solicitud (pero sirve para cada solicitud, por lo que no es lo mínimo posible).

-module(hello). 
-export([start/1]). 

start(Port) -> 
    spawn(fun() -> {ok, Sock} = gen_tcp:listen(Port, [{active, false}]), 
        loop(Sock) end). 

loop(Sock) -> 
    {ok, Conn} = gen_tcp:accept(Sock), 
    Handler = spawn(fun() -> handle(Conn) end), 
    gen_tcp:controlling_process(Conn, Handler), 
    loop(Sock). 

handle(Conn) -> 
    gen_tcp:send(Conn, response("Hello World")), 
    gen_tcp:close(Conn). 

response(Str) -> 
    B = iolist_to_binary(Str), 
    iolist_to_binary(
     io_lib:fwrite(
     "HTTP/1.0 200 OK\nContent-Type: text/html\nContent-Length: ~p\n\n~s", 
     [size(B), B])). 
+3

Consulte '{packet, http}' para 'Opciones' de' gen_tcp: listen' para decodificar encabezados HTTP. – Pindatjuh

+1

Estaba viendo este código, y aunque parece limpio, encontré un problema. Al probarlo con Apache Bench, obtengo un 'apr_socket_recv: Connection reset by peer (104)'. funciona bien cuando se accede desde un navegador o usando curl. ¿Tienes alguna idea de por qué es esto? –

+1

@MartinKristiansen Eliminar la línea 'gen_tcp: cerrar (Conn) .' –

8

¿De verdad quieres escribir un servidor web en Erlang, o quieres un servidor web Erlang para poder crear contenido web dinámico usando Erlang?

Si es el último, intente YAWS. Si es el primero, eche un vistazo al YAWS source code para obtener inspiración

+2

Quiero crear contenido dinámico, pero solo quería saber el mínimo indispensable para un servidor web. Miré el código fuente de Yaws y mi primera impresión fue que se necesitaba mucho código. – Zubair

12

Para un servidor web que utiliza únicamente las bibliotecas integradas, echa un vistazo a inets http_server. Cuando necesite un poco más de potencia pero aún con simplicidad, debe consultar la biblioteca mochiweb. Puedes google para un montón de código de ejemplo.

+1

Eso es genial, así que al usar INets ¿puedo escribir un servidor web de un solo módulo? – Zubair

1

Solo una solución para la respuesta de Felix y aborda los problemas que está viendo Martin. Antes de cerrar un socket, se deben recibir todos los datos que se envían desde el cliente (utilizando, por ejemplo, do_recv desde gen_tcp description).

De lo contrario, hay una condición de carrera para que el navegador/proxy envíe la solicitud HTTP lo suficientemente rápido como para enviar la solicitud http antes de que se cierre el socket.

2

Otra forma, similar al ejemplo anterior gen_tcp pero con menos código y ya se ofrece como sugerencia, es usar el inets library.

%%% 
%%% A simple "Hello, world" server in the Erlang. 
%%% 

-module(hello_erlang). 
-export([ 
    main/1, 
    run_server/0, 
    start/0 
]). 

main(_) -> 
    start(), 
    receive 
    stop -> ok 
    end. 

run_server() -> 
    ok = inets:start(), 
    {ok, _} = inets:start(httpd, [ 
    {port, 0}, 
    {server_name, "hello_erlang"}, 
    {server_root, "/tmp"}, 
    {document_root, "/tmp"}, 
    {bind_address, "localhost"} 
    ]). 

start() -> run_server().              

Tenga en cuenta, esto expone su directorio /tmp.

para correr, simplemente:

$ escript ./hello_erlang.erl 
Cuestiones relacionadas