Golang Http Request

Source: Internet
Author: User
Tags rfc
This is a creation in Article, where the information may have evolved or changed.

Take a look at Golang's HTTP packet. How to write Request information

Let's take a look at the struct of Golang HTTP request, do not explain, take a slow look (HTTP authoritative guide, RFC document)

type request struct {// method specifies the http method  (GET,  post, put, etc.).  for client requests an empty string means get. method string// url specifies either the uri being requested  (for  server// requests)  or the URL to access  (for client  Requests).//// for server requests the url is parsed from the  uri// supplied on the request-line as stored in requesturi.   for// most requests, fields other than path and rawquery  will be// empty.  (see rfc 2616, section 5.1.2)//// for  Client requests, the url ' S host specifies the server to// connect  to, while&nbSp;the request ' S host field optionally// specifies the host header  value to send in the http// request. Url *url. Url// the protocol version for incoming requests.// client requests  always use HTTP/1.1.Proto      string //  "http/1.0" protomajor int    // 1protominor int    // 0//  A header maps request lines to their values.// If the  header says////accept-encoding: gzip, deflate//accept-language: en-us//connection:  keep-alive//// then////header = map[string][]string{//"accept-encoding":  {"gzip,  Deflate "},//" accept-language ":  {" en-US "},//" Connection ":  {" keep-alive "},//}//// http  Defines that header names are case-insensitive.// the request parser implements this by canonicalizing  the// name, making the first character and any characters//  following a hyphen uppercase and the rest lowercase.//// for  Client requests certain headers are automatically// added and may  override values in header.//// see the documentation for the  request.write method. Header header// body is the request ' s body.//// for client  Requests a nil body means the request has no// body, such  as a get request. the http client ' s transport// is  Responsible for calling the close method.//// for server requests  the request body is always non-nil// but will return eof immediately  when no body is present.// The Server will close the  Request body. the servehttp// handler does not need to. Body io. readcloser// contentlength records the length of the associated  content.// the value -1 indicates that the length is unknown.//  values >= 0 indicate that the given number of bytes  may// be read from body.// for client requests, a value  of 0 means unknown if body is not nil. Contentlength int64// transferencoding lists the transfer encodings from  outermost to// innermost. an empty list denotes the  "Identity"  encoding.// transferencoding can usually  be ignored; chunked encoding is// automatically added and  Removed as necessary when sending and// receiving requests. transferencoding []string// close indicates whether to close the  connection after// replying to this request  (for servers)  or  after sending// the request  (for clients). close bool// for server requests host specifies the host on  Which the// url is sought. per rfc 2616, this is either  the value of// the  "Host"  header or the host name  Given in the url itself.// it may be of the form  "Host:port".//// for client requests host optionally overrides the  Host// header to send. If empty, the Request.Write method  Uses// the value of url. host.host string// form contains the parsed form data, including  Both the url// field ' S query parameters and the post or put  form data.// This field is only available after ParseForm  is called.// the http client ignores form and uses body  instead. Form url. Values// postform contains the parsed form data from post or  put// body parameters.// this field is only available after  parseform is called.// the http client  Ignores postform and uses body instead. Postform url. Values// multipartform is the parsed multipart form, including file  uploads.// this field is only available after parsemultipartform  is called.// the http client ignores multipartform and uses  body instead. Multipartform *multipart. form// trailer specifies additional headers that are sent after  the request// body.//// for server requests the trailer map  initially contains only the// trailer keys, with nil values.  (The  client declares which trailers it// will later send.)   while the handler is reading from body, it must// not  reference&nbSp Trailer. after reading from body returns eof, trailer// can be  read again and will contain non-nil values, if they were  sent// by the client.//// For client requests Trailer must  be initialized to a map containing// the trailer keys to  Later send. the values may be nil or their final// values.  the contentlength must be 0 or -1, to send a chunked  request.// after the http request is sent the map values  can be updated while// the request body is read. Once  the body returns eof, the caller must// not mutate trailer.////  Few HTTP Clients, servers, or proxies support http trailers. Trailer header// remoteaddr allows http servers and other software  to record// the network address that sent the request,  usually for// logging. this field is not filled in by  readrequest and// has no defined format. the http server in  this package// sets remoteaddr to an  "Ip:port"  address before  invoking a// handler.// this field is ignored by the http  Client. remoteaddr string// requesturi is the unmodified request-uri of the//  Request-Line  (rfc 2616, section 5.1)  as sent by the client/ / to a server. usually the&nbsp url field should be used instead.// it is an error to  Set this field in an http client request. Requesturi string// tls allows http servers and other software to  record// information about the TLS connection on which the  request// was received. this field is not filled in by  Readrequest.// the http server in this package sets the field  for// tls-enabled connections before invoking a handler;// otherwise  it leaves the field nil.// This field is ignored by  The http client. Tls *tls. ConnectionState}

to specifically analyze the specific execution flow of HTTP request write

func  (req *request)  write (W io. Writer, usingproxy bool, extraheaders header)  error {host := req. hostif host ==  ""  {if req. Url == nil {return errors. New ("Http: request.write on request with no host or url set")} Host = req. Url. Host}ruri := req. Url. RequestUri ()//proxy mode when Ruri need to add protocol name Http/https such as If usingproxy && req. Url. scheme !=  ""  && req. Url. opaque ==  ""  {ruri = req. Url. scheme +  "://"  + host + ruri} else if req. method ==  "CONNECT"  && req. Url. path ==  ""  {// connect requests normally give just the host  and port, not a full url.ruri = host}// todo (Bradfitz):  Escape at least newlines in ruri?// Wrap the writer in a bufio Writer  If it ' S not already buffered.// don ' T always call newwriter, as  that forces a bytes. buffer// and other small bufio writers to have a minimum 4k  buffer// size.//creates a writer that writes content Var bw *bufio. Writerif _, ok := w. (IO. Bytewriter);  !ok {bw = bufio. Newwriter (W) w = bw}                 //writes the HTTP start data _, err := fmt. fprintf (w,  "%s %s http/1.1\r\n",  valueordefault (req. method,  "GET"),  ruri) if err != nil {return err}// header lines   Write host content _, err = fmt. fprintf (w,  "host: %s\r\n",  host) If err != nil {return err}// use the defaultuseragent unless the header contains  one, which// may be blank to not send the header.//The data for this thing are as follows:/*  const defaultUserAgent =  "Go 1.1 package http"  */useragent :=  defaultuseragentif req. Header != nil {if ua := req. header["User-agent"]; len (UA)  > 0 {userAgent = ua[0]}}if userAgent  !=  ""  {_, err = fmt. fprintf (w,  "user-agent: %s\r\n",  useragent) If err != nil {return err}} The transferwriter structure of the  process body,contentlength,close,trailer//package tw, err :=  Newtransferwriter (req) if err != nil {return err}err = tw. Writeheader (W) if err != nil {return err}err = req. Header.writesubset (W, reqwriteexcludeheAder) if err != nil {return err}if extraheaders != nil {err =  extraheaders.write (W) if err != nil {return err}}_, err = io. WriteString (w,  "\ r \ n") If err != nil {return err}// write body and  trailererr = tw. Writebody (W) if err != nil {return err}if bw != nil {return  Bw. Flush ()}return nil}

Let's take a look at the Transferwriter structure-related operations:

The Body,contentlength,close,trailertype transferwriter struct {Method string Body io that is used primarily for writing HTTP. Readerbodycloser io. Closerresponsetohead boolcontentlength Int64//-1 means unknown, 0 means exactly noneclose booltransferen coding []stringtrailer Header}

To create a transferwriter process:

Func newtransferwriter (r interface{})   (T *transferwriter, err error)  {t  = &transferWriter{}// Extract relevant fieldsatLeastHTTP11 :=  Falseswitch rr := r. (type)  {case *request:if rr. Contentlength != 0 && rr. Body == nil {return nil, fmt. Errorf ("Http: request.contentlength=%d with nil body",  rr. ContentLength)}t.method = rr. Methodt.body = rr. Bodyt.bodycloser = rr. Bodyt.contentlength = rr. Contentlengtht.close = rr. Closet.transferencoding = rr. Transferencodingt.trailer = rr. Traileratleasthttp11 = rr. Protoatleast (1, 1) If t.body != nil && len (t.TransferEncoding)  ==  0 && atleasthttp11 {if t.contentlength == 0 {// test  to see if it ' s actually zero or just unset.var buf [1]byten, rerr :=  io. Readfull (t.body, buf[:]) If rerr != nil && rerr != io. Eof {t.contentlength = -1t. Body = &errorreader{rerr}} else if n == 1 {// oh, guess  there is data in this Body Reader after all.// The  Contentlength field just wasn ' t set.// stich the body back  Together again, re-attaching our// consumed byte.t.contentlength = -1t. Body = io. Multireader (bytes. Newreader (buf[:]),  t.body)} else {// body is actually empty.t.body =  nilt. Bodycloser = nil}}if t.contentlength < 0 {t.transferencoding = [] string{"chunked"}}}case *response:if rR.request != nil {t.method = rr. Request.method}t.body = rr. Bodyt.bodycloser = rr. Bodyt.contentlength = rr. Contentlengtht.close = rr. Closet.transferencoding = rr. Transferencodingt.trailer = rr. Traileratleasthttp11 = rr. Protoatleast (1, 1) t.responsetohead = nobodyexpected (T.method)}// sanitize body, Contentlength,transferencodingif t.responsetohead {t.body = nilif chunked (T. transferencoding)  {t.contentlength = -1}} else {if !atleasthttp11 | |  t.body == nil {t.transferencoding = nil}if chunked (t.TransferEncoding)  {t.contentlength = -1} else if t.body == nil { // no  chunking, no bodyt. Contentlength = 0}}// sanitize trailerif !chunked (t.transferencoding)  {t.Trailer  = nil}retUrn t, nil} 

Finally, take a look at Writebody's operation:

func  (T *transferwriter)  writebody (W io. Writer)  error {var err errorvar ncopy int64// Write body  Write Body operation here if t.body != nil { if chunked (t.transferencoding)  {cw :=  internal. Newchunkedwriter (W) _, err = io. Copy (cw, t.body) IF&NBSP;ERR&NBSP;==&NBSP;NIL&NBSP;{ERR&NBSP;=&NBSP;CW. Close ()}} else if t.contentlength == -1 {ncopy, err = io. Copy (w, t.body)} else {ncopy, err = io. Copy (W, io. Limitreader (t.body, t.contentlength)) If err != nil {return err}var nextra  int64nextra, err = io. Copy (Ioutil. Discard, t.body) Ncopy += nextra}if err != nil {return err}if err  = t.bodycloser.close ();  err != nil {return err}}if !t.responsetohead  && t.conTentlength != -1 && t.contentlength != ncopy {return fmt. Errorf ("http: contentlength=%d with body length %d", T.contentlength, ncopy)}//  todo (Petar):  place trailer writer code here.if chunked (t.TransferEncoding)  {// write trailer headerif t.trailer != nil {if err :=  t.trailer.write (w);  err != nil {return err}}// last chunk, empty  trailer_, err = io. WriteString (w,  "\ r \ n")}return err}

implementing the HTTP server itself can be used for reference here code

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.