7 Jul 2013 eMBee   » (Journeyer)

basic http file server

I needed to quickly serve some files, and i didn't want to install a full webserver, knowing that this was only temporary. So instead here is a simple http file-server in Pike. I call it a file-server because it serves static files, and nothing else.

Based on this example for a simple web-server, it just takes a few additions to turn this into a file-server:

#!/usr/local/bin/pike

constant default_port = 8080;
constant my_version = "0.0";

Protocols.HTTP.Server.Port port;

string basedir = "/srv/www";

int main(int argc, array(string) argv)
{
  int my_port = default_port;
  if(argc>1) my_port=(int)argv[1];

  write("SocServe starting on port %d\n", my_port);

  port = Protocols.HTTP.Server.Port(handle_request, my_port);
  return -1;
}

void handle_request(Protocols.HTTP.Server.Request request)
{
  write(sprintf("got request: %O\n", request));

  mapping response = ([]);

  response->server="SocServe " + my_version;

  string target = Stdio.append_path(basedir, request->not_query);
  mixed tstat = file_stat(target);
  write("target: %O\n", tstat);

  if (tstat 
&
& tstat->isdir)
  {
    response->type = "text/html";
    response->error = 200;
    response->data = dirlist(target);
  } 
  else if (tstat 
&
& tstat->isreg)
  {
    response->type = MIME.ext_to_media_type((target/".")[-1]) || "octet/stream";
    response->error = 200;
    response->file = Stdio.File(target);
  }
  else
  {
    response->type = "text/html";
    response->error = 200;
    response->request = sprintf("%O", mkmapping(indices(request), values(request)));
    response->data = "<h1>SocServe " + my_version + "</h1>n<pre>"
    + response->request + "</pre>n";
  }

  request->response_and_finish(response);
}

string dirlist(string path)
{ 
  array dir = get_dir(path);
  return sprintf("%{<a href=\"%s\">%s</a><br>\n%}", ({ dir[*], dir[*] })); 
}

These are the changes: first combine the request path with our basedir which will reduce any embedded /../ to not go beyond that base. Then we check if it's a directory or a file. For a directory we make a simple listing, and for a file we find the mime-type and then just open the file and pass it to the request. This will cause the file to be served with non-blocking I/O, allowing you to handle multiple requests in parallel without blocking the server while a file is being downloaded.

That's all there is to it. Start it up, and it's ready to serve files.

Syndicated 2013-07-07 17:51:04 from DevLog

Latest blog entries     Older blog entries

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!