ページ

2009年11月13日

Goで超いい加減HTTPサーバ

超いい加減HTTPサーバを今はやりのGoで書いてみました。とってもいい加減です。カレントディレクトリのファイルをフィードしてくれます。ヘッダーのパースは、最低限のことしかしていません。レスポンスヘッダーもHTTP/1.0 200 OKしかかえしません。エラーがでたら無条件でブチッとコネクションを切ります。
goroutine楽です。connを閉じる場所が美しくないので、変えたい。


感想はこっち

package main

import (
"os";
"net";
"syscall";
"strings";
"fmt";
)

func Err(format string, v ...) {
fmt.Fprintf(os.Stderr, format + "\n", v)
}

func Msg(format string, v ...) {
fmt.Fprintf(os.Stdout, format + "\n", v)
}

func main() {
runServer()
}

func runServer() {
l, err := net.Listen("tcp", "127.0.0.1:1972");
if err != nil {
Err("Failed to Listen to 1972");
}
for {
conn, err := l.Accept();
if err != nil {
Err("Accept %s", err);
break
}
Msg("Request came");
go processRequest(conn);
}
}

func processRequest(conn net.Conn) {
defer conn.Close();

buffer := make([]byte, 1024);
headers := "";
for {
l, err := conn.Read(buffer);
if err == nil {
b := buffer[0:l];
headers += string(b);
count := len(headers);
if headers[count-4:count] == "\r\n\r\n" {
break;
}
} else if err == os.EOF {
Msg("EOF");
return;
} else {
Err("Err%s", err);
return;
}
}
url := strings.Split(headers, " ", 3)[1];
url = url[1:len(url)];
if len(url) == 0 || url[len(url)-1] == '/' {
url += "index.html";
}
fd, err1 := syscall.Open(url, syscall.O_RDONLY, 0);
if err1 == 0 {
conn.Write(strings.Bytes("HTTP/1.0 200 OK\r\n\r\n"));
fb := make([]byte, 1024);
for {
l, e := syscall.Read(fd, fb);
if e == 0 {
conn.Write(fb[0:l]);
}
if l == 0 {
break;
}
}
syscall.Close(fd);
}
Msg("done");
}

0 件のコメント: