golang的net/http包

刘地 · · 14357 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

package http

import "net/http"

http包提供了HTTP客户端和服务端的实现。

GetHeadPostPostForm函数发出HTTP/ HTTPS请求。

resp, err := http.Get("http://example.com/")
...
resp, err := http.Post("http://example.com/upload", "image/jpeg", &buf)
...
resp, err := http.PostForm("http://example.com/form",
	url.Values{"key": {"Value"}, "id": {"123"}})

程序在使用完回复后必须关闭回复的主体。

resp, err := http.Get("http://example.com/")
if err != nil {
	// handle error
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
// ...

要管理HTTP客户端的头域、重定向策略和其他设置,创建一个Client

client := &http.Client{
	CheckRedirect: redirectPolicyFunc,
}

resp, err := client.Get("http://example.com")
// ...

req, err := http.NewRequest("GET", "http://example.com", nil)
// ...
req.Header.Add("If-None-Match", `W/"wyzzy"`)
resp, err := client.Do(req)
// ...

要管理代理、TLS配置、keep-alive、压缩和其他设置,创建一个Transport

tr := &http.Transport{
	TLSClientConfig:    &tls.Config{RootCAs: pool},
	DisableCompression: true,
}
client := &http.Client{Transport: tr}
resp, err := client.Get("https://example.com")

ClientTransport类型都可以安全的被多个go程同时使用。出于效率考虑,应该一次建立、尽量重用。

ListenAndServe使用指定的监听地址和处理器启动一个HTTP服务端。处理器参数通常是nil,这表示采用包变量DefaultServeMux作为处理器。HandleHandleFunc函数可以向DefaultServeMux添加处理器。

http.Handle("/foo", fooHandler)

http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
})

log.Fatal(http.ListenAndServe(":8080", nil))

要管理服务端的行为,可以创建一个自定义的Server

s := &http.Server{
	Addr:           ":8080",
	Handler:        myHandler,
	ReadTimeout:    10 * time.Second,
	WriteTimeout:   10 * time.Second,
	MaxHeaderBytes: 1 << 20,
}
log.Fatal(s.ListenAndServe())

Index

Examples

Constants

const ( StatusContinue = 100 StatusSwitchingProtocols = 101 StatusOK = 200 StatusCreated = 201 StatusAccepted = 202 StatusNonAuthoritativeInfo = 203 StatusNoContent = 204 StatusResetContent = 205 StatusPartialContent = 206 StatusMultipleChoices = 300 StatusMovedPermanently = 301 StatusFound = 302 StatusSeeOther = 303 StatusNotModified = 304 StatusUseProxy = 305 StatusTemporaryRedirect = 307 StatusBadRequest = 400 StatusUnauthorized = 401 StatusPaymentRequired = 402 StatusForbidden = 403 StatusNotFound = 404 StatusMethodNotAllowed = 405 StatusNotAcceptable = 406 StatusProxyAuthRequired = 407 StatusRequestTimeout = 408 StatusConflict = 409 StatusGone = 410 StatusLengthRequired = 411 StatusPreconditionFailed = 412 StatusRequestEntityTooLarge = 413 StatusRequestURITooLong = 414 StatusUnsupportedMediaType = 415 StatusRequestedRangeNotSatisfiable = 416 StatusExpectationFailed = 417 StatusTeapot = 418 StatusInternalServerError = 500 StatusNotImplemented = 501 StatusBadGateway = 502 StatusServiceUnavailable = 503 StatusGatewayTimeout = 504 StatusHTTPVersionNotSupported = 505
)

HTTP状态码,参见RFC 2616

const DefaultMaxHeaderBytes = 1 << 20 // 1 MB

DefaultMaxHeaderBytesHTTP请求的头域最大允许长度。可以通过设置Server.MaxHeaderBytes字段来覆盖。

const DefaultMaxIdleConnsPerHost = 2

DefaultMaxIdleConnsPerHostTransportMaxIdleConnsPerHost的默认值。

const TimeFormat = "Mon, 02 Jan 2006 15:04:05 GMT"

TimeFormat是当解析或生产HTTP头域中的时间时,用与time.Parsetime.Format函数的时间格式。这种格式类似time.RFC1123但强制采用GMT时区。

Variables

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"}
)

HTTP请求的解析错误。

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")
)

会被HTTP服务端返回的错误。

var DefaultClient = &Client{}

DefaultClient是用于包函数GetHeadPost的默认Client

var DefaultServeMux = NewServeMux()

DefaultServeMux是用于Serve的默认ServeMux

var ErrBodyReadAfterClose = errors.New("http: invalid Read on closed Body")

ResquestResponseBody字段已经关闭后,试图从中读取时,就会返回ErrBodyReadAfterClose。这个错误一般发生在:HTTP处理器中调用完ResponseWriter 接口的WriteHeaderWrite后从请求中读取数据的时候。

var ErrHandlerTimeout = errors.New("http: Handler timeout")

在处理器超时以后调用ResponseWriter接口的Write方法,就会返回ErrHandlerTimeout

var ErrLineTooLong = errors.New("header line too long")
var ErrMissingFile = errors.New("http: no such file")

当请求中没有提供给FormFile函数的文件字段名,或者该字段名不是文件字段时,该函数就会返回ErrMissingFile

var ErrNoCookie = errors.New("http: named cookie not present")
var ErrNoLocation = errors.New("http: no Location header in response")

type ProtocolError

type ProtocolError struct { ErrorString string }

HTTP请求解析错误。

func (*ProtocolError) Error

func (err *ProtocolError) Error() string

func CanonicalHeaderKey

func CanonicalHeaderKey(s string) string

CanonicalHeaderKey函数返回头域(表示为Header类型)的键s的规范化格式。规范化过程中让单词首字母和'-'后的第一个字母大写,其余字母小写。例如,"accept-encoding"规范化为"Accept-Encoding"

func DetectContentType

func DetectContentType(data []byte) string

DetectContentType函数实现了http://mimesniff.spec.whatwg.org/描述的算法,用于确定数据的Content-Type。函数总是返回一个合法的MIME类型;如果它不能确定数据的类型,将返回"application/octet-stream"。它最多检查数据的前512字节。

func ParseHTTPVersion

func ParseHTTPVersion(vers string) (major, minor int, ok bool)

ParseHTTPVersion解析HTTP版本字符串。如"HTTP/1.0"返回(1, 0, true)

func ParseTime

func ParseTime(text string) (t time.Time, err error)

ParseTime3种格式TimeFormat, time.RFC850time.ANSIC尝试解析一个时间头的值(如Date: header)。

func StatusText

func StatusText(code int) string

StatusText返回HTTP状态码code对应的文本,如220对应"OK"。如果code是未知的状态码,会返回""

type ConnState

type ConnState int

ConnState代表一个客户端到服务端的连接的状态。本类型用于可选的Server.ConnState回调函数。

const ( // StateNew代表一个新的连接,将要立刻发送请求。 // 连接从这个状态开始,然后转变为StateAliveStateClosed StateNew ConnState = iota // StateActive代表一个已经读取了请求数据1到多个字节的连接。 // 用于StateAliveServer.ConnState回调函数在将连接交付给处理器之前被触发, // 等到请求被处理完后,Server.ConnState回调函数再次被触发。 // 在请求被处理后,连接状态改变为StateClosedStateHijackedStateIdle StateActive // StateIdle代表一个已经处理完了请求、处在闲置状态、等待新请求的连接。 // 连接状态可以从StateIdle改变为StateActiveStateClosed StateIdle // 代表一个被劫持的连接。这是一个终止状态,不会转变为StateClosed StateHijacked // StateClosed代表一个关闭的连接。 // 这是一个终止状态。被劫持的连接不会转变为StateClosed StateClosed )

func (ConnState) String

func (c ConnState) String() string

type Header

type Header map[string][]string

Header代表HTTP头域的键值对。

func (Header) Get

func (h Header) Get(key string) string

Get返回键对应的第一个值,如果键不存在会返回""。如要获取该键对应的值切片,请直接用规范格式的键访问map

func (Header) Set

func (h Header) Set(key, value string)

Set添加键值对到h,如键已存在则会用只有新值一个元素的切片取代旧值切片。

func (Header) Add

func (h Header) Add(key, value string)

Add添加键值对到h,如键已存在则会将新的值附加到旧值切片后面。

func (Header) Del

func (h Header) Del(key string)

Del删除键值对。

func (Header) Write

func (h Header) Write(w io.Writer) error

Write以有线格式将头域写入w

func (Header) WriteSubset

func (h Header) WriteSubset(w io.Writer, exclude map[string]bool) error

WriteSubset以有线格式将头域写入w。当exclude不为nil时,如果h的键值对的键在exclude中存在且其对应值为真,该键值对就不会被写入w

type Cookie

type Cookie struct { Name string Value string Path string Domain string Expires time.Time RawExpires string // MaxAge=0表示未设置Max-Age属性 // MaxAge<0表示立刻删除该cookie,等价于"Max-Age: 0" // MaxAge>0表示存在Max-Age属性,单位是秒 MaxAge int Secure bool HttpOnly bool Raw string Unparsed []string // 未解析的“属性-值”对的原始文本 }

Cookie代表一个出现在HTTP回复的头域中Set-Cookie头的值里或者HTTP请求的头域中Cookie头的值里的HTTP cookie

func (*Cookie) String

func (c *Cookie) String() string

String返回该cookie的序列化结果。如果只设置了NameValue字段,序列化结果可用于HTTP请求的Cookie头或者HTTP回复的Set-Cookie头;如果设置了其他字段,序列化结果只能用于HTTP回复的Set-Cookie头。

type CookieJar

type CookieJar interface { // SetCookies管理从u的回复中收到的cookie // 根据其策略和实现,它可以选择是否存储cookie SetCookies(u *url.URL, cookies []*Cookie) // Cookies返回发送请求到u时应使用的cookie // 本方法有责任遵守RFC 6265规定的标准cookie限制 Cookies(u *url.URL) []*Cookie }

CookieJar管理cookie的存储和在HTTP请求中的使用。CookieJar的实现必须能安全的被多个go程同时使用。

net/http/cookiejar包提供了一个CookieJar的实现。

type Request

type Request struct { // Method指定HTTP方法(GETPOSTPUT等)。对客户端,""代表GET Method string // URL在服务端表示被请求的URI,在客户端表示要访问的URL // // 在服务端,URL字段是解析请求行的URI(保存在RequestURI字段)得到的, // 对大多数请求来说,除了PathRawQuery之外的字段都是空字符串。 // (参见RFC 2616, Section 5.1.2 // // 在客户端,URLHost字段指定了要连接的服务器, // 而RequestHost字段(可选地)指定要发送的HTTP请求的Host头的值。 URL *url.URL // 接收到的请求的协议版本。本包生产的Request总是使用HTTP/1.1 Proto string // "HTTP/1.0" ProtoMajor int // 1 ProtoMinor int // 0 // Header字段用来表示HTTP请求的头域。如果头域(多行键值对格式)为: //	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中的特定的头,参见Request.Write方法。 Header Header // Body是请求的主体。 // // 在客户端,如果Bodynil表示该请求没有主体买入GET请求。 // ClientTransport字段会负责调用BodyClose方法。 // // 在服务端,Body字段总是非nil的;但在没有主体时,读取Body会立刻返回EOF // Server会关闭请求的主体,ServeHTTP处理器不需要关闭Body字段。 Body io.ReadCloser // ContentLength记录相关内容的长度。 // 如果为-1,表示长度未知,如果>=0,表示可以从Body字段读取ContentLength字节数据。 // 在客户端,如果Bodynil而该字段为0,表示不知道Body的长度。 ContentLength int64 // TransferEncoding按从最外到最里的顺序列出传输编码,空切片表示"identity"编码。 // 本字段一般会被忽略。当发送或接受请求时,会自动添加或移除"chunked"传输编码。 TransferEncoding []string // Close在服务端指定是否在回复请求后关闭连接,在客户端指定是否在发送请求后关闭连接。 Close bool // 在服务端,Host指定URL会在其上寻找资源的主机。 // 根据RFC 2616,该值可以是Host头的值,或者URL自身提供的主机名。 // Host的格式可以是"host:port" // // 在客户端,请求的Host字段(可选地)用来重写请求的Host头。 // 如过该字段为""Request.Write方法会使用URL字段的Host。 Host string // Form是解析好的表单数据,包括URL字段的query参数和POSTPUT的表单数据。 // 本字段只有在调用ParseForm后才有效。在客户端,会忽略请求中的本字段而使用Body替代。 Form url.Values // PostForm是解析好的POSTPUT的表单数据。 // 本字段只有在调用ParseForm后才有效。在客户端,会忽略请求中的本字段而使用Body替代。 PostForm url.Values // MultipartForm是解析好的多部件表单,包括上传的文件。 // 本字段只有在调用ParseMultipartForm后才有效。 // 在客户端,会忽略请求中的本字段而使用Body替代。 MultipartForm *multipart.Form // Trailer指定了会在请求主体之后发送的额外的头域。 // // 在服务端,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 // 一般应使用URI字段,在客户端设置请求的本字段会导致错误。 RequestURI string // TLS字段允许HTTP服务器和其他软件记录接收到该请求的TLS连接的信息 // 本字段不是ReadRequest函数填写的。 // 对启用了TLS的连接,本包的HTTP服务器会在调用处理器之前设置TLS字段,否则将设TLSnil // 客户端会忽略请求中的TLS字段。 TLS *tls.ConnectionState }

Request类型代表一个服务端接受到的或者客户端发送出去的HTTP请求。

Request各字段的意义和用途在服务端和客户端是不同的。除了字段本身上方文档,还可参见Request.Write方法和RoundTripper接口的文档。

func NewRequest

func NewRequest(method, urlStr string, body io.Reader) (*Request, error)

NewRequest使用指定的方法、网址和可选的主题创建并返回一个新的*Request

如果body参数实现了io.Closer接口,Request返回值的Body 字段会被设置为body,并会被Client类型的DoPostPostFOrm方法以及Transport.RoundTrip方法关闭。

func ReadRequest

func ReadRequest(b *bufio.Reader) (req *Request, err error)

ReadRequestb读取并解析出一个HTTP请求。(本函数主要用在服务端从下层获取请求)

func (*Request) ProtoAtLeast

func (r *Request) ProtoAtLeast(major, minor int) bool

ProtoAtLeast报告该请求使用的HTTP协议版本至少是major.minor

func (*Request) UserAgent

func (r *Request) UserAgent() string

UserAgent返回请求中的客户端用户代理信息(请求的User-Agent头)。

func (*Request) Referer

func (r *Request) Referer() string

Referer返回请求中的访问来路信息。(请求的Referer头)

Referer在请求中就是拼错了的,这是HTTP早期就有的错误。该值也可以从用Header["Referer"]获取; 让获取Referer字段变成方法的好处是,编译器可以诊断使用正确单词拼法的req.Referrer()的程序,但却不能诊断使用Header["Referrer"]的程序。

func (*Request) AddCookie

func (r *Request) AddCookie(c *Cookie)

AddCookie向请求中添加一个cookie。按照RFC 6265 section 5.4的跪地,AddCookie不会添加超过一个Cookie头字段。这表示所有的cookie都写在同一行,用分号分隔(cookie内部用逗号分隔属性)。

func (*Request) SetBasicAuth

func (r *Request) SetBasicAuth(username, password string)

SetBasicAuth使用提供的用户名和密码,采用HTTP基本认证,设置请求的Authorization头。HTTP基本认证会明码传送用户名和密码。

func (*Request) Write

func (r *Request) Write(w io.Writer) error

Write方法以有线格式将HTTP/1.1请求写入w(用于将请求写入下层TCPConn等)。本方法会考虑请求的如下字段:

Host
URL
Method (defaults to "GET")
Header
ContentLength
TransferEncoding
Body

如果存在BodyContentLength字段<= 0TransferEncoding字段未显式设置为["identity"]Write方法会显式添加"Transfer-Encoding: chunked"到请求的头域。Body字段会在发送完请求后关闭。

func (*Request) WriteProxy

func (r *Request) WriteProxy(w io.Writer) error

WriteProxy类似Write但会将请求以HTTP代理期望的格式发送。

尤其是,按照RFC 2616 Section 5.1.2WriteProxy会使用绝对URI(包括协议和主机名)来初始化请求的第1行(Request-URI行)。无论何种情况,WriteProxy都会使用r.Hostr.URL.Host设置Host头。

func (*Request) Cookies

func (r *Request) Cookies() []*Cookie

Cookies解析并返回该请求的Cookie头设置的cookie

func (*Request) Cookie

func (r *Request) Cookie(name string) (*Cookie, error)

Cookie返回请求中名为namecookie,如果未找到该cookie会返回nil, ErrNoCookie

func (*Request) ParseForm

func (r *Request) ParseForm() error

ParseForm解析URL中的查询字符串,并将解析结果更新到r.Form字段。

对于POSTPUT请求,ParseForm还会将body当作表单解析,并将结果既更新到r.PostForm也更新到r.Form。解析结果中,POSTPUT请求主体要优先于URL查询字符串(同名变量,主体的值在查询字符串的值前面)。

如果请求的主体的大小没有被MaxBytesReader函数设定限制,其大小默认限制为开头10MB

ParseMultipartForm会自动调用ParseForm。重复调用本方法是无意义的。

func (*Request) ParseMultipartForm

func (r *Request) ParseMultipartForm(maxMemory int64) error

ParseMultipartForm将请求的主体作为multipart/form-data解析。请求的整个主体都会被解析,得到的文件记录最多maxMemery字节保存在内存,其余部分保存在硬盘的temp文件里。如果必要,ParseMultipartForm会自行调用ParseForm。重复调用本方法是无意义的。

func (*Request) FormValue

func (r *Request) FormValue(key string) string

FormValue返回key为键查询r.Form字段得到结果[]string切片的第一个值。POSTPUT主体中的同名参数优先于URL查询字符串。如果必要,本函数会隐式调用ParseMultipartFormParseForm

func (*Request) PostFormValue

func (r *Request) PostFormValue(key string) string

PostFormValue返回key为键查询r.PostForm字段得到结果[]string切片的第一个值。如果必要,本函数会隐式调用ParseMultipartFormParseForm

func (*Request) FormFile

func (r *Request) FormFile(key string) (multipart.File, *multipart.FileHeader, error)

FormFile返回以key为键查询r.MultipartForm字段得到结果中的第一个文件和它的信息。如果必要,本函数会隐式调用ParseMultipartF


有疑问加站长微信联系(非本文作者)

本文来自:开源中国博客

感谢作者:刘地

查看原文:golang的net/http包

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

14357 次点击  ∙  1 赞  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传