http包包含http客户端和服务端的实现,利用Get,Head,Post,以及PostForm实现HTTP或者HTTPS的请求.
当客户端使用完response body后必须使用close对其进行关闭.如下所示
resp, err := http.Get("http://example.com/") if err != nil { // handle error } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) // ...
变量:
以下错误是http server使用的
var ( ErrHeaderTooLong = &ProtocolError{"header too long"} ErrShortBody = &ProtocolError{"entity body too short"} ErrNotSupported = &ProtocolError{"feature not supported"} ErrUnexpectedTrailer = &ProtocolError{"trailer header without chunked transfer encoding"} ErrMissingContentLength = &ProtocolError{"missing ContentLength in HEAD response"} ErrNotMultipart = &ProtocolError{"request Content-Type isn‘t multipart/form-data"} ErrMissingBoundary = &ProtocolError{"no multipart boundary param in Content-Type"} ) var ( ErrWriteAfterFlush = errors.New("Conn.Write called after Flush") ErrBodyNotAllowed = errors.New("http: request method or response status code does not allow body") ErrHijacked = errors.New("Conn has been hijacked") ErrContentLength = errors.New("Conn.Write wrote more than the declared Content-Length") )
var DefaultClient = &Client{} //默认客户端,被Get,Head以及Post使用
var DefaultServeMux = NewServeMux()//Serve使用的默认ServeMux
var ErrBodyReadAfterClose = errors.New("http: invalid Read on closed Body")//当读取一个request或者response body是在这个body已经关闭之后,便会返回该错误.这种错误主要发生情况是:当http handler调用writeheader或者write关于responsewrite之后进行读操作.
var ErrHandlerTimeout = errors.New("http: Handler timeout")//超时错误
var ErrLineTooLong = internal.ErrLineTooLong//当读取格式错误的分块编码时便会出现该错误.
var ErrMissingFile = errors.New("http: no such file")//当利用FormFile进行文件请求时,如果文件不存在或者请求中没有该文件就会出现该错误.
var ErrNoCookie = errors.New("http: named cookie not present") var ErrNoLocation = errors.New("http: no Location header in response")
type Client struct { // Transport指定执行独立、单次HTTP请求的机制如果Transport为nil,则使用DefaultTransport。 Transport RoundTripper // CheckRedirect指定处理重定向的策略,如果CheckRedirect非nil,client将会在调用重定向之前调用它。 // 参数req和via是将要执行的请求和已经执行的请求(时间越久的请求优先执行),如果CheckRedirect返回一个错误,
//client的GetGet方法不会发送请求req,而是回之前得到的响应和该错误。 // 如果CheckRedirect为nil,会采用默认策略:在连续10次请求后停止。 CheckRedirect func(req *Request, via []*Request) error // Jar指定cookie管理器,如果Jar为nil,在请求中不会发送cookie,在回复中cookie也会被忽略。 Jar CookieJar // Timeout指定Client请求的时间限制,该超时限制包括连接时间、重定向和读取response body时间。 // 计时器会在Head,Get,Post或Do方法返回后开始计时并在读到response.body后停止计时。 // Timeout为零值表示不设置超时。 // Client的Transport字段必须支持CancelRequest方法,否则Client会在尝试用Head,Get,Post或Do方法执行请求时返回错误。 // Client的Transport字段默认值(DefaultTransport)支持CancelRequest方法。 Timeout time.Duration }
type CloseNotifier interface { // 当客户端断开连接时,CloseNotifier接受一个通知 CloseNotify() <-chan bool }
type ConnState int
其中ConnState常用状态变量如下:
const ( // StateNew代表一个新的连接,将要立刻发送请求。 // 连接从这个状态开始,然后转变为StateAlive或StateClosed。 StateNew ConnState = iota // StateActive代表一个已经读取了请求数据1到多个字节的连接。 // 用于StateAlive的Server.ConnState回调函数在将连接交付给处理器之前被触发, // 等到请求被处理完后,Server.ConnState回调函数再次被触发。 // 在请求被处理后,连接状态改变为StateClosed、StateHijacked或StateIdle。 StateActive // StateIdle代表一个已经处理完了请求、处在闲置状态、等待新请求的连接。 // 连接状态可以从StateIdle改变为StateActive或StateClosed。 StateIdle // 代表一个被劫持的连接。这是一个终止状态,不会转变为StateClosed。 StateHijacked // StateClosed代表一个关闭的连接。 // 这是一个终止状态。被劫持的连接不会转变为StateClosed。 StateClosed )
type Cookie struct {
Name string //名字 Value string //值 Path string //路径 Domain string Expires time.Time //过期时间 RawExpires string // MaxAge=0 意味着 没有‘Max-Age‘属性指定. // MaxAge<0 意味着 立即删除cookie // MaxAge>0 意味着设定了MaxAge属性,并且其单位是秒 MaxAge int Secure bool HttpOnly bool Raw string Unparsed []string // 未解析的属性值对 }
func (c *Cookie) String() string//该函数返回cookie的序列化结果。如果只设置了Name和Value字段,序列化结果可用于HTTP请求的Cookie头或者HTTP回复的Set-Cookie头;如果设置了其他字段,序列化结果只能用于HTTP回复的Set-Cookie头。
type CookieJar interface { // SetCookies 处理从rul接收到的cookie,是否存储这个cookies取决于jar的策略和实现 SetCookies(u *url.URL, cookies []*Cookie) // Cookies 返回发送到指定url的cookies Cookies(u *url.URL) []*Cookie }
type Dir string
type File interface { io.Closer io.Reader Readdir(count int) ([]os.FileInfo, error) Seek(offset int64, whence int) (int64, error) Stat() (os.FileInfo, error) }
type FileSystem interface { Open(name string) (File, error) }
type Flusher interface { // Flush将任何缓存数据发送到client Flush() }
type Handler interface { ServeHTTP(ResponseWriter, *Request) }
type HandlerFunc func(ResponseWriter, *Request)
type Header map[string][]string
type Hijacker interface { // Hijack让调用者接管连接,在调用Hijack()后,http server库将不再对该连接进行处理,对于该连接的管理和关闭责任将由调用者接管. Hijack() (net.Conn, *bufio.ReadWriter, error) }
type Request struct { // Method指定HTTP方法(GET,POST,PUT等)默认使用GET方法。 Method string // URL在服务端表示被请求的URI(uniform resource identifier,统一资源标识符),在客户端表示要访问的URL。 // 在服务端,URL字段是解析请求行的URI(保存在RequestURI字段)得到的,对大多数请求来说,除了Path和RawQuery之外的字段都是空字符串。 // 在客户端,URL的Host字段指定了要连接的服务器,而Request的Host字段指定要发送的HTTP请求的Host头的值。 URL *url.URL // 接收到的请求的协议版本。client的Request总是使用HTTP/1.1 Proto string // "HTTP/1.0" ProtoMajor int // 1 ProtoMinor int // 0 // Header字段用来表示HTTP请求的头域。如果header(多行键值对格式)为: // accept-encoding: gzip, deflate // Accept-Language: en-us // Connection: keep-alive // 则: // Header = map[string][]string{ // "Accept-Encoding": {"gzip, deflate"}, // "Accept-Language": {"en-us"}, // "Connection": {"keep-alive"}, // } // HTTP规定header的键名(头名)是区分大小写的,请求的解析器通过规范化头域的键名来实现这点,即首字母大写,其他字母小写,通过"-"进行分割。 // 在客户端的请求,可能会被自动添加或重写Header中的特定的头,参见Request.Write方法。 Header Header // Body是请求的主体.对于客户端请求来说,一个nil body意味着没有body,http Client的Transport字段负责调用Body的Close方法。 // 在服务端,Body字段总是非nil的;但在没有主体时,读取Body会立刻返回EOF.Server会关闭请求主体,而ServeHTTP处理器不需要关闭Body字段。 Body io.ReadCloser // ContentLength记录相关内容的长度.如果为-1,表示长度未知,如果values>=0,表示可以从Body字段读取ContentLength字节数据。 // 在客户端,如果Body非nil而该字段为0,表示不知道Body的长度。 ContentLength int64 // TransferEncoding按从最外到最里的顺序列出传输编码,空切片表示"identity"编码。 // 本字段一般会被忽略。当发送或接受请求时,会自动添加或移除"chunked"传输编码。 TransferEncoding []string // Close在服务端指定是否在回复请求后关闭连接,在客户端指定是否在发送请求后关闭连接。 Close bool // 对于服务器端请求,Host指定URL指向的主机,可能的格式是host:port.对于客户请求,Host用来重写请求的Host头,如过该字段为"",Request.Write方法会使用URL.Host来进行赋值。 Host string // Form是解析好的表单数据,包括URL字段的query参数和POST或PUT的表单数据.本字段只有在调用ParseForm后才有效。在客户端,会忽略请求中的本字段而使用Body替代。 Form url.Values // PostForm是解析好的POST或PUT的表单数据.本字段只有在调用ParseForm后才有效。在客户端,会忽略请求中的本字段而使用Body替代。 PostForm url.Values // MultipartForm是解析好的多部件表单,包括上传的文件.本字段只有在调用ParseMultipartForm后才有效。http客户端中会忽略MultipartForm并且使用Body替代 MultipartForm *multipart.Form // Trailer指定了在发送请求体之后额外的headers,在服务端,Trailer字段必须初始化为只有trailer键,所有键都对应nil值。 // (客户端会声明哪些trailer会发送)在处理器从Body读取时,不能使用本字段.在从Body的读取返回EOF后,Trailer字段会被更新完毕并包含非nil的值。 // (如果客户端发送了这些键值对),此时才可以访问本字段。 // 在客户端,Trail必须初始化为一个包含将要发送的键值对的映射.(值可以是nil或其终值),ContentLength字段必须是0或-1,以启用"chunked"传输编码发送请求。 // 在开始发送请求后,Trailer可以在读取请求主体期间被修改,一旦请求主体返回EOF,调用者就不可再修改Trailer。 // 几乎没有HTTP客户端、服务端或代理支持HTTP trailer。 Trailer Header // RemoteAddr允许HTTP服务器和其他软件记录该请求的来源地址,该字段经常用于日志.本字段不是ReadRequest函数填写的,也没有定义格式。 // 本包的HTTP服务器会在调用处理器之前设置RemoteAddr为"IP:port"格式的地址.客户端会忽略请求中的RemoteAddr字段。 RemoteAddr string // RequestURI是客户端发送到服务端的请求中未修改的URI(参见RFC 2616,Section 5.1),如果在http请求中设置该字段便会报错. RequestURI string // TLS字段允许HTTP服务器和其他软件记录接收到该请求的TLS连接的信息,本字段不是ReadRequest函数填写的。 // 对启用了TLS的连接,本包的HTTP服务器会在调用处理器之前设置TLS字段,否则将设TLS为nil。 // 客户端会忽略请求中的TLS字段。 TLS *tls.ConnectionState }
func NewRequest(method, urlStr string, body io.Reader) (*Request, error) //利用指定的method,url以及可选的body返回一个新的请求.如果body参数实现了io.Closer接口,Request返回值的Body 字段会被设置为body,并会被Client类型的Do、Post和PostFOrm方法以及Transport.RoundTrip方法关闭。
如果存在Body,ContentLength字段<= 0且TransferEncoding字段未显式设置为["identity"],Write方法会显式添加"Transfer-Encoding: chunked"到请求的头域。Body字段会在发送完请求后关闭。
type Response struct { Status string // 例如"200 OK" StatusCode int // 例如200 Proto string // 例如"HTTP/1.0" ProtoMajor int // 主协议号:例如1 ProtoMinor int // 副协议号:例如0 // Header保管header的key values,如果response中有多个header中具有相同的key,那么Header中保存为该键对应用逗号分隔串联起来的这些头的值// 被本结构体中的其他字段复制保管的头(如ContentLength)会从Header中删掉。Header中的键都是规范化的,参见CanonicalHeaderKey函数 Header Header // Body代表response的主体。http的client和Transport确保这个body永远非nil,即使response没有body或body长度为0。调用者也需要关闭这个body// 如果服务端采用"chunked"传输编码发送的回复,Body字段会自动进行解码。 Body io.ReadCloser // ContentLength记录相关内容的长度。 // 其值为-1表示长度未知(采用chunked传输编码) // 除非对应的Request.Method是"HEAD",其值>=0表示可以从Body读取的字节数 ContentLength int64 // TransferEncoding按从最外到最里的顺序列出传输编码,空切片表示"identity"编码。 TransferEncoding []string // Close记录头域是否指定应在读取完主体后关闭连接。(即Connection头) // 该值是给客户端的建议,Response.Write方法的ReadResponse函数都不会关闭连接。 Close bool // Trailer字段保存和头域相同格式的trailer键值对,和Header字段相同类型 Trailer Header // Request是用来获取此回复的请求,Request的Body字段是nil(因为已经被用掉了)这个字段是被Client类型发出请求并获得回复后填充的 Request *Request // TLS包含接收到该回复的TLS连接的信息。 对未加密的回复,本字段为nil。返回的指针是被(同一TLS连接接收到的)回复共享的,不应被修改。 TLS *tls.ConnectionState }
301 (永久重定向,告诉客户端以后应该从新地址访问) 302 (暂时性重定向,作为HTTP1.0的标准,以前叫做Moved Temporarily,现在叫做Found。现在使用只是为了兼容性处理,包括PHP的默认Location重定向用到也是302),注:303和307其实是对302的细化。 303 (对于Post请求,它表示请求已经被处理,客户端可以接着使用GET方法去请求Location里的URl) 307 (临时重定向,对于Post请求,表示请求还没有被处理,客户端应该向Location里的URL重新发起Post请求)
//如果有太多次重定向或者有一个http协议错误将会导致错误。当err为nil时,resp总是包含一个非nil的resp.body,Get是对DefaultClient.Get的一个包装。
type ResponseWriter interface { // Header返回一个Header类型值,该值会被WriteHeader方法发送.在调用WriteHeader或Write方法后再改变header值是不起作用的。 Header() Header // WriteHeader该方法发送HTTP回复的头域和状态码。如果没有被显式调用,第一次调用Write时会触发隐式调用WriteHeader(http.StatusOK) // 因此,显示调用WriterHeader主要用于发送错误状态码。 WriteHeader(int) // Write向连接中写入数据,该数据作为HTTP response的一部分。如果被调用时还没有调用WriteHeader,本方法会先调用WriteHeader(http.StatusOK) // 如果Header中没有"Content-Type"键,本方法会使用包函数DetectContentType检查数据的前512字节,将返回值作为该键的值。 Write([]byte) (int, error) }
type RoundTripper interface { // RoundTrip执行单次HTTP事务,返回request的response,RoundTrip不应试图解析该回复。 // 尤其要注意,只要RoundTrip获得了一个回复,不管该回复的HTTP状态码如何,它必须将返回值err设置为nil。 // 非nil的返回值err应该留给获取回复失败的情况。类似的,RoundTrip不能试图管理高层协议,如重定向、认证或者cookie。 // RoundTrip除了从请求的主体读取并关闭主体之外,不能够对请求做任何修改,包括(请求的)错误。 // RoundTrip函数接收的请求的URL和Header字段必须保证是初始化了的。 RoundTrip(*Request) (*Response, error) }
t := &http.Transport{} t.RegisterProtocol("file", http.NewFileTransport(http.Dir("/"))) c := &http.Client{Transport: t} res, err := c.Get("file:///etc/passwd") ...
注意,因为以斜杠结尾的模式代表一个由根开始的子树,模式"/"会匹配所有的未被其他注册的模式匹配的路径,而不仅仅是路径"/"。
模式也能(可选地)以主机名开始,表示只匹配该主机上的路径。指定主机的模式优先于一般的模式,因此一个注册了两个模式"/codesearch"和"codesearch.google.com/"的处理器不会接管目标为"http://www.google.com/"的请求。
ServeMux还会负责对URL路径的过滤,将任何路径中包含"."或".."元素的请求重定向到等价的没有这两种元素的URL。(参见path.Clean函数)
mux := http.NewServeMux() mux.Handle("/api/", apiHandler{}) mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { // The "/" pattern matches everything, so we need to check // that we‘re at the root here. if req.URL.Path != "/" { http.NotFound(w, req) return } fmt.Fprintf(w, "Welcome to the home page!") })
type Server struct { Addr string // 监听的TCP地址,如果为空字符串会使用":http" Handler Handler // 调用的处理器,如为nil会调用http.DefaultServeMux ReadTimeout time.Duration // 请求的读取操作在超时前的最大持续时间 WriteTimeout time.Duration // 回复的写入操作在超时前的最大持续时间 MaxHeaderBytes int // 请求的头域最大长度,如为0则用DefaultMaxHeaderBytes TLSConfig *tls.Config // 可选的TLS配置,用于ListenAndServeTLS方法 // TLSNextProto(可选地)指定一个函数来在一个NPN型协议升级出现时接管TLS连接的所有权。 // 映射的键为商谈的协议名;映射的值为函数,该函数的Handler参数应处理HTTP请求, // 并且初始化Handler.ServeHTTP的*Request参数的TLS和RemoteAddr字段(如果未设置)。 // 连接在函数返回时会自动关闭。 TLSNextProto map[string]func(*Server, *tls.Conn, Handler) // ConnState字段指定一个可选的回调函数,该函数会在一个与客户端的连接改变状态时被调用。 // 参见ConnState类型和相关常数获取细节。 ConnState func(net.Conn, ConnState) // ErrorLog指定一个可选的日志记录器,用于记录接收连接时的错误和处理器不正常的行为。 // 如果本字段为nil,日志会通过log包的标准日志记录器写入os.Stderr。 ErrorLog *log.Logger // 内含隐藏或非导出字段 }
func (srv *Server) ListenAndServe() error//监听TCP网络地址srv.Addr然后调用Serve来处理接下来连接的请求。如果srv.Addr是空的话,则使用“:http”。
type Transport struct { // Proxy指定一个对给定请求返回代理的函数。如果该函数返回了非nil的错误值,请求的执行就会中断并返回该错误。 // 如果Proxy为nil或返回nil的*URL置,将不使用代理。 Proxy func(*Request) (*url.URL, error) // Dial指定创建未加密TCP连接的dial函数。如果Dial为nil,会使用net.Dial。 Dial func(network, addr string) (net.Conn, error)
// DialTls利用一个可选的dial函数来为非代理的https请求创建一个TLS连接。如果DialTLS为nil的话,那么使用Dial和TLSClientConfig。
//如果DialTLS被设定,那么Dial钩子不被用于HTTPS请求和TLSClientConfig并且TLSHandshakeTimeout被忽略。返回的net.conn默认已经经过了TLS握手协议。
DialTLS func(network, addr string) (net.Conn, error) // TLSClientConfig指定用于tls.Client的TLS配置信息。如果该字段为nil,会使用默认的配置信息。 TLSClientConfig *tls.Config // TLSHandshakeTimeout指定等待TLS握手完成的最长时间。零值表示不设置超时。 TLSHandshakeTimeout time.Duration // 如果DisableKeepAlives为真,不同HTTP请求之间TCP连接的重用将被阻止。 DisableKeepAlives bool // 如果DisableCompression为真,会禁止Transport在请求中没有Accept-Encoding头时, // 主动添加"Accept-Encoding: gzip"头,以获取压缩数据。 // 如果Transport自己请求gzip并得到了压缩后的回复,它会主动解压缩回复的主体。 // 但如果用户显式的请求gzip压缩数据,Transport是不会主动解压缩的。 DisableCompression bool // 如果MaxIdleConnsPerHost不为0,会控制每个主机下的最大闲置连接数目。 // 如果MaxIdleConnsPerHost为0,会使用DefaultMaxIdleConnsPerHost。 MaxIdleConnsPerHost int // ResponseHeaderTimeout指定在发送完请求(包括其可能的主体)之后, // 等待接收服务端的回复的头域的最大时间。零值表示不设置超时。 // 该时间不包括读取回复主体的时间。 ResponseHeaderTimeout time.Duration }
---恢复内容结束---
原文:http://www.cnblogs.com/msnsj/p/4365186.html