golang server.go 处理head请求的一个小坑

前端之家收集整理的这篇文章主要介绍了golang server.go 处理head请求的一个小坑前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

虽然是个小坑,可是trace了一个星期,浪费了不少时间,解决方案很简单,思考的过程却是很值得借鉴:)

http web完整代码在:https://github.com/philsong/golang_samples/tree/master/src/emvdecoder



emvdecoder中问题代码片段如下:

func checkError(w http.ResponseWriter,err error) {
	if err != nil {
		fmt.Fprintf(w,"Fatal error ",err.Error())
		os.Exit(1)
	}
}

func index(w http.ResponseWriter,r *http.Request) {
	r.ParseForm()

	t,err := template.ParseFiles("index.html")
	checkError(w,err)

	err = t.Execute(w,emvdecoder)
	checkError(w,err)
}


问题出现了: 刚开始用ssh登陆到ubuntu,然后运行emvdecoder&后,断开ssh,然后过一会就发现web已经连不上了。。。怀疑是输入输出的问题,猜测程序可能被信号中断之类的,于是微博发一信息请教牛人:“ 请教你个问题,我有个程序xxx,用ssh登录到linux,然后运行xxx&跑到后台,可以通过 http://t.cn/z8oSEpF 访问,然后断开ssh之后,这个xxx就好像挂掉了,请问什么原因? @by_jack @李先静ABSURD_AT_CSDN @CodeBox-腾讯 @许式伟”,自然是没有得到任何人的反馈,牛人都很忙:)

于是自己就搜索google,发现了这篇文章Linux 技巧:让进程在后台可靠运行的几种方法http://www.jb51.cc/article/p-nmsbedla-bnx.html


用nohupemvdecoder&运行后,似乎运行良好了(稍后就知道这是巧合。。。),于是发一微博

“哥找到原因了,解决方案:让进程在后台可靠运行的几种方法 http://t.cn/hBEhmq”

结果晚上回家一运行,又挂了,靠,不死心,难道nohup有问题,于是用setsid,过了一天还是不行

继续测试发现其实无论用&, nohup还是setsid, 父进程已经变成了init了,所以效果其实一样,于是猜测是代码的bug(其实又是自己的问题...),但是奇怪为什么没打印出来呢

philsong@compiler:~$ cd go/src/emvdecoder/
philsong@compiler:~/go/src/emvdecoder$ emvdecoder&
[1] 22908

philsong@compiler:~/go/src/emvdecoder$ ps
PID TTY TIME CMD
22729 pts/2 00:00:01 bash
22908 pts/2 00:00:00 emvdecoder
22911 pts/2 00:00:00 ps

philsong@compiler:~/go/src/emvdecoder$ pstree -ps 22908
init(1)---sshd(702)---sshd(22703)---sshd(22728)---bash(22729)---emvdecoder(22908)-+-{emvdecoder}(22909)
`-{emvdecoder}(22910)
断开ssh后,

philsong@compiler:~$ pstree -ps 22908
init(1)---emvdecoder(22908)-+-{emvdecoder}(22909)
|-{emvdecoder}(22910)
|-{emvdecoder}(22916)
`-{emvdecoder}(22917)

fuck代码发现

func checkError(w http.ResponseWriter,err.Error())
		os.Exit(1)
	}
}


fmt.Fprintf(w
由于copy时默认打印到http 的w句柄,并没有打印道控制台,囧啊,改为
fmt.Println("

继续log大法,并打印堆栈

import "runtime/debug"

debug.PrintStack()

func checkError(w http.ResponseWriter,err error) {
	fmt.Println("error: ")
	if err != nil {
		fmt.Println("Fatal error ",err.Error())
		debug.PrintStack()
		os.Exit(1)
	}
}

func index(w http.ResponseWriter,r *http.Request) {
	println("Request ",r.URL.Path," from ",r.RemoteAddr)
	//   path := r.URL.Path[1:]
	path := "." + r.URL.Path

	fmt.Println("path",path)
	if path == "./favicon.ico" {
		http.NotFound(w,r)
		return
	}

	r.ParseForm()

	t,err)
}

这次捕获到珍贵的输出

Request / from 208.94.145.109:22492
path ./
error:
error:

Fatal error template: index.html:1:0: executing "index.html" at <"<!DOCTYPE HTML>\r\n...>: http: request method or response status code does not allow body
/home/philsong/go/src/emvdecoder/emvdecoder.go:47 (0x8048d50)
checkError: debug.PrintStack()
/home/philsong/go/src/emvdecoder/emvdecoder.go:69 (0x80490a5)
index: checkError(w,err)
/usr/local/go/src/pkg/net/http/server.go:1149 (0x809936c)
HandlerFunc.ServeHTTP: f(w,r)
/usr/local/go/src/pkg/net/http/server.go:1416 (0x809a39d)
(*ServeMux).ServeHTTP: h.ServeHTTP(w,r)
/usr/local/go/src/pkg/net/http/server.go:1517 (0x809aa21)
serverHandler.ServeHTTP: handler.ServeHTTP(rw,req)
/usr/local/go/src/pkg/net/http/server.go:1096 (0x8099073)
(*conn).serve: serverHandler{c.server}.ServeHTTP(w,w.req)
/usr/local/go/src/pkg/runtime/proc.c:1223 (0x805fd60)
goexit: runtime路goexit(void)


奇怪,发现208.94.145.109的访问,这是神吗东西,爬虫吗?

googlehttp: request method or response status code does not allow body

The error is self-explaining:

request method or response status code does not allow body

A HEAD request only allows HTTP headers to be sent back as response.


   899	func (w *response) Write(data []byte) (n int,err error) {
   900		if w.conn.hijacked() {
   901			log.Print("http: response.Write on hijacked connection")
   902			return 0,ErrHijacked
   903		}
   904		if !w.wroteHeader {
   905			w.WriteHeader(StatusOK)
   906		}
   907		if len(data) == 0 {
   908			return 0,nil
   909		}
   910		if !w.bodyAllowed() {
   911			return 0,ErrBodyNotAllowed
   912		}
   913	
   914		w.written += int64(len(data)) // ignoring errors,for errorKludge
   915		if w.contentLength != -1 && w.written > w.contentLength {
   916			return 0,ErrContentLength
   917		}
   918		return w.w.Write(data)
   919	}
猜测是发起的head请求,不是正常的get和post请求,怪不得,直接用浏览器访问时无法重现这个bug,于是用
philsong@compiler:~$ curl -I 192.168.7.14:9090
curl: (52) Empty reply from server

测试,果然崩溃了,崩溃信息一致,到此bug定位了。。。

修复方案:注释掉

		//os.Exit(1)

再次运行:
philsong@compiler:~$ curl -I 192.168.7.14:9090
HTTP/1.1 200 OK
Date: Tue,17 Sep 2013 06:31:32 GMT


philsong@compiler:~$ curl -I 192.168.7.14:9090
HTTP/1.1 200 OK
Date: Tue,17 Sep 2013 06:31:40 GMT

GOD,一切正常了:)小伙伴们开心的笑了。。。。

猜你在找的Go相关文章