設定要求
応答モードでの相互作用のHTTPリクエストとレスポンス。私たちが見ているだろう要求、2番目のパラメータhttp.Requestsハンドラ機能を行きます。その構造は次のとおりです。
type Request struct {
Method string
URL *url.URL
Proto string // "HTTP/1.0"
ProtoMajor int // 1
ProtoMinor int // 0
Header Header
Body io.ReadCloser
ContentLength int64
TransferEncoding []string
Close bool
Host string
Form url.Values
PostForm url.Values
MultipartForm *multipart.Form
....
ctx context.Context
}
あなたは、基本的な情報は、すべてのHTTPリクエストを包含し、要求の構造から見ることができます。要求、要求されたURL、メソッド、ヘッダー、これらの構造のボディについての主な関心事のために。
URL
HTTP URL形式手法への要求:// [userinfoを@]ホスト /パス[#fragment]、ゴーは、 HTTPリクエストURL [?クエリ]をマッピングするために使用されるURLの構造を、提供します。
type URL struct {
Scheme string
Opaque string
User *Userinfo
Host string
Path string
RawQuery string
Fragment string
}
URLの形式は、実際に、それはより良い用語URI、ユニフォームリソースロケータである必要があり、比較的明確です。より重要なURLクエリ文字列クエリです。通常のGETリクエストのパラメータとして。符号分割&KEY1 =値1&KEY2 = value2のキーと値のペアを使用して、いくつかのクエリ、URLはASSICコーディングコード、およびクエリでurlencode用従って必要であるからです。request.URI.RawQueryで読み取り、クエリを行きます
func indexHandler(w http.ResponseWriter, r *http.Request) {
info := fmt.Sprintln("URL", r.URL, "HOST", r.Host, "Method", r.Method, "RequestURL", r.RequestURI, "RawQuery", r.URL.RawQuery)
fmt.Fprintln(w, info)
}
☁ ~ curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d 'name=vanyar&age=27' "http://127.0.0.1:8000?lang=zh&version=1.1.0"
URL /?lang=zh&version=1.1.0 HOST 127.0.0.1:8000 Method POST RequestURL /?lang=zh&version=1.1.0 RawQuery lang=zh&version=1.1.0
ヘッダ
、ヘッダHTTPの重要な部分。リクエストヘッダ構造は、構造を有し、ヘッダは、本質的にマップ(マップ[文字列] []の文字列)。図マップとしてキー値のHTTPプロトコル・ヘッダ:
Host: example.com
accept-encoding: gzip, deflate
Accept-Language: en-us
fOO: Bar
foo: two
Header = map[string][]string{
"Accept-Encoding": {"gzip, deflate"},
"Accept-Language": {"en-us"},
"Foo": {"Bar", "two"},
}
ヘッダフィールドは、多くの場合、コンテンツタイプを指定して要求し、通信設定の多くが含まれています。
func indexHandler(w http.ResponseWriter, r *http.Request) {
info := fmt.Sprintln(r.Header.Get("Content-Type"))
fmt.Fprintln(w, info)
}
☁ ~ curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d 'name=vanyar&age=27' "http://127.0.0.1:8000?lang=zh&version=1.1.0"
ファイルアプリケーション/ x-www-form-urlencodedで
Golng印刷は基本的に3つのカテゴリー3分割、多くの機能を提供します。printlnとのprintfを印刷しておくこと。
、比較的単純な印刷標準出力ストリームに印刷され、printlnのマルチプリント改行ことを除いて同じ。printfの書式文字列が印刷されるように、この方法は、3バイトの印刷の数を返します。スプリントは、Sprinln sprintfの文字列と印刷はありません標準出力ストリームに、返されます。FPRINT、このオブジェクトにio.Writer、HTTPインタフェース出力を置く関数fprintf Fprinln印刷がhttp.ReponseWriterある結果、印刷枚数バイトに戻ります。
ボディ
本体を介して送信されたHTTPデータ通信、。ReadCloserインタフェースであるパッケージ本体ボディリクエスト、に入ります。リーダインタフェースメソッドは、Read(P []バイト)(持つインターフェースである N INT、ERRエラー) このようにバイト配列を読み取ることによって、要求されたデータ缶体を得る、方法。
func indexHandler(w http.ResponseWriter, r *http.Request) {
info := fmt.Sprintln(r.Header.Get("Content-Type"))
len := r.ContentLength
body := make([]byte, len)
r.Body.Read(body)
fmt.Fprintln(w, info, string(body))
}
☁ ~ curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d 'name=vanyar&age=27' "http://127.0.0.1:8000?lang=zh&version=1.1.0"
application/x-www-form-urlencoded
name=vanyar&age=27
可见,当请求的content-type为application/x-www-form-urlencoded, body也是和query一样的格式,key-value的键值对。换成json的请求方式则如下:
☁ ~ curl -X POST -H "Content-Type: application/json" -d '{name: "vanyar", age: 27}' "http://127.0.0.1:8000?lang=zh&version=1.1.0"
application/json
{name: "vanyar", age: 27}
multipart/form-data的格式用来上传图片,请求的body如下:
☁ ~ curl -X POST -H "Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW" -F "name=vanyar" -F "age=27" "http://127.0.0.1:8000?lang=zh&version=1.1.0"
multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW; boundary=------------------------d07972c7800e4c23
--------------------------d07972c7800e4c23
Content-Disposition: form-data; name="name"
vanyar
--------------------------d07972c7800e4c23
Content-Disposition: form-data; name="age"
27
--------------------------d07972c7800e4c23--
フォーム
の解析体は、クライアントによって要求されたデータを読み取ることができます。そして、このデータは、より原始的であるかどうかまたはフォーム・データのデータへの鍵です。読む直接非常に面倒に解決。ボディは通常、提供されたデータを形成します。したがって、これらのゴーフォームデータを処理する方法を提供します。
Form1の
移動は、提供されたデータ分析ParseFormフォーム、X-WWW-フォームでurlencodeデータ、すなわち、コンテンツ・タイプのための方法を提供します。
func indexHandler(w http.ResponseWriter, r *http.Request) {
contentType := fmt.Sprintln(r.Header.Get("Content-Type"))
r.ParseForm()
fromData := fmt.Sprintf("%#v", r.Form)
fmt.Fprintf(w, contentType, fromData)
}
☁ ~ curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d 'name=vanyar&age=27' "http://127.0.0.1:8000?lang=zh&version=1.1.0"
application/x-www-form-urlencoded
%!(EXTRA string=url.Values{"name":[]string{"vanyar"}, "age":[]string{"27"}, "lang":[]string{"zh"}, "version":[]string{"1.1.0"}})%
データ構造とを読み取るための方法は、一般的に、いくつか以下があります。
fmt.Println(r.Form["lang"])
fmt.Println(r.PostForm["lang"])
fmt.Println(r.FormValue("lang"))
fmt.Println(r.PostFormValue("lang"))
ParseFormを呼び出した後でなければなりませんR.Formとr.PostFormは、我々はそれ以外の場合は空の配列で、データを持っています。
必要性のParseFormなしコールr.FormValueとr.PostFormValue(「LANG」)は、データを読み取ることができます。
さらにr.Formとr.PostFormアレイ構造であるが、同じ名前のURLのパラメータは、体内に存在すると、r.Formアレイと接頭POSTで、二つの値、すなわち[「EN」、「ZHを」]有しこの方法では、データは本体のみを読み取ることができます。
☁ ~ curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d 'name=vanyar&age=27&lang=en' "http://127.0.0.1:8000?lang=zh&version=1.1.0"
application/x-www-form-urlencoded
%!(EXTRA string=url.Values{"version":[]string{"1.1.0"}, "name":[]string{"vanyar"}, "age":[]string{"27"}, "lang":[]string{"en", "zh"}})%
あなたが見ることができる。この時点で、LANGパラメータだけでなく、ポストの体も提供しては、デフォルトの優先度データのボディに行くURLクエリ、両方のデータを持って提供し、カバーしません。
あなたは、URLパラメータ、またはコールPostForm値を読みたくない場合はPostFormValueフィールドを読み取ることができます。
r.PostForm["lang"][0]
r.PostFormValue["lang"]
对于form-data的格式的数据,ParseForm的方法只会解析url中的参数,并不会解析body中的参数。
☁ ~ curl -X POST -H "Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW" -F "name=vanyar" -F "age=27" -F "lang=en" "http://127.0.0.1:8000?lang=zh&version=1.1.0"
multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW; boundary=------------------------5f87d5bfa764488d
%!(EXTRA string=url.Values{"lang":[]string{"zh"}, "version":[]string{"1.1.0"}}
)%
そうでない場合r.Fromは体の内容を読んでいないときに、フォームデータ要求のコンテンツタイプを使用すると、MutilpartFromを変更する必要がある場合、ParseFrom、したがって、あなただけのクエリ文字列の内容を読み取ることができます。
MutilpartFrom
ParseMutilpartFromメソッドは、パラメータの読み取りデータ長を提供伴い、その後、フォームデータを読み取る同じ方法を使用し、MutilpartFrom本体はデータのみを読み込み、データのクエリは、URLを読み取れません。
func indexHandler(w http.ResponseWriter, r *http.Request) {
r.ParseMultipartForm(1024)
fmt.Println(r.Form["lang"])
fmt.Println(r.PostForm["lang"])
fmt.Println(r.FormValue("lang"))
fmt.Println(r.PostFormValue("lang"))
fmt.Println(r.MultipartForm.Value["lang"])
fmt.Fprintln(w, r.MultipartForm.Value)
}
戻る[名前を:[ヴァンヤール]年齢:[27]のlang:[EN]]は、マップ要求の後見ることができます。それr.MultipartForm.Valueと、URLのパラメータなし。
要約すると、読み出しでurlencodeエンコーディング、ParseFormのみメソッドをコードするフォームデータを読み取るために必要ParseMultipartFormの使用を必要とします。両方のパラメータがURL場合は、別のボディから、及び場合、fromValue方法を読み取ることができます。ポスト接頭辞方法は、本体のみのデータ内容を読み取ることができます。前記データは、MultipartForm r.MultipartForm.Valueのアクセスを得ました。
ファイルアップロード
フォームデータ形式最も使用方法は、時間の写真をアップロードすることです。r.MultipartForm.Valueはフィールドデータポストのボディで、r.MultipartForm.Fileは、画像データが含まれています。
func indexHandler(w http.ResponseWriter, r *http.Request) {
r.ParseMultipartForm(1024)
fileHeader := r.MultipartForm.File["file"][0]
fmt.Println(fileHeader)
file, err := fileHeader.Open()
if err == nil{
data, err := ioutil.ReadAll(file)
if err == nil{
fmt.Println(len(data))
fmt.Fprintln(w, string(data))
}
}
fmt.Println(err)
}
リクエストを発行した後、あなたは返すの画像を見ることができます。もちろん、より良いツールがr.FormFile、アップロードファイルを直接読み込んだデータを機能提供して行きます。ParseMultipartFormメソッドを使用する必要はありません。
file, _, err := r.FormFile("file")
if err == nil{
data, err := ioutil.ReadAll(file)
if err == nil{
fmt.Println(len(data))
fmt.Fprintln(w, string(data))
}
}
fmt.Println(err)
NOの場合、他のフィールドそれでもLANGパラメータ、またはParseMultipartForm呼び出しを追加する必要が読む必要がある場合にのみ、ケースファイルのフィールドに適用されます。ファイルをアップロードするために読んで、次のステップは、動作するために非常に一般的なIO書き込みファイルがあります。
JSONは
、分離の終わり頃、今通常、JSON形式に慣れていくつかのフレームワークによって提出されたクライアントデータの上昇、角度、VUE、反応し、人気があります。JSON形式の場合は、身体のJSON文字列は、ネイティブです。つまり、の行くJSONデータ構造を解読するために行きます。
type Person struct {
Name string
Age int
}
func indexHandler(w http.ResponseWriter, r *http.Request) {
decode := json.NewDecoder(r.Body)
var p Person
err := decode.Decode(&p)
if err != nil{
log.Fatalln(err)
}
info := fmt.Sprintf("%T\n%#v\n", p, p)
fmt.Fprintln(w, info)
}
☁ ~ curl -X POST -H "Content-Type: application/json" -d '{"name": "vanyar", "age": 27 }' "http://127.0.0.1:8000?lang=zh&version=1.1.0"
main.Person
main.Person{Name:"vanyar", Age:27}
JSONの詳細については、ずっと後の議論。詳細については、公式サイトのドキュメントを参照してください。
応答
要求と応答は、同様のメッセージ・フォーマット、関連するプロセスと構造が類似している彼らだけではなく、双子の兄弟、httpです。ゴー構造は、応答ResponseWriterインターフェイスで構成されています。
type ResponseWriter interface {
Header() Header
Write([]byte) (int, error)
WriteHeader(int)
}
この方法は非常に簡単である内部ヘッダ方法は、ヘッダ構造のマップを返します。WriteHeader応答ステータスコードが返されます。クライアントデータへの書き込みバック。
私たちは、データがW応答に直接書き込まれ、fmt.Fprintlnメソッドを使用しています。また、メソッドの戻りを書く文字を呼び出すことができます。
func indexHandler(w http.ResponseWriter, r *http.Request) {
str := `<html>
<head><title>Go Web Programming</title></head>
<body><h1>Hello World</h1></body>
</html>`
w.Write([]byte(str))
}
☁ ~ curl -i http://127.0.0.1:8000/
HTTP/1.1 200 OK
Date: Wed, 07 Dec 2016 09:13:04 GMT
Content-Length: 95
Content-Type: text/html; charset=utf-8
<html>
<head><title>Go Web Programming</title></head>
<body><h1>Hello World</h1></body>
</html>%
☁ ~
go根据返回的字符,自动修改成了text/html的Content-Type格式。返回数据自定义通常需要修改header相关信息。
func indexHandler(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(501)
fmt.Fprintln(w, "No such service, try next door")
}
☁ ~ curl -i http://127.0.0.1:8000/
HTTP/1.1 501 Not Implemented
Date: Wed, 07 Dec 2016 09:14:58 GMT
Content-Length: 31
Content-Type: text/plain; charset=utf-8
No such service, try next door
リダイレクト
リダイレクト機能を達成するための場所とHTTPヘッダのステータスコードを設定します。
func indexHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Location", "https://google.com")
w.WriteHeader(302)
}
☁ ~ curl -i http://127.0.0.1:8000/
HTTP/1.1 302 Found
Location: https://google.com
Date: Wed, 07 Dec 2016 09:20:19 GMT
Content-Length: 31
Content-Type: text/plain; charset=utf-8
重定向是常用的功能,因此go也提供了工具方法,http.Redirect(w, r, "https://google.com", http.StatusFound)。
リクエストヘッダ構造と同様に、w.Headerヘッダを設定するには、いくつかの方法があります
func (h Header) Add(key, value string) {
textproto.MIMEHeader(h).Add(key, value)
}
func (h Header) Set(key, value string) {
textproto.MIMEHeader(h).Set(key, value)
}
func (h MIMEHeader) Add(key, value string) {
key = CanonicalMIMEHeaderKey(key)
h[key] = append(h[key], value)
}
func (h MIMEHeader) Set(key, value string) {
h[CanonicalMIMEHeaderKey(key)] = []string{value}
}
セットと方法を追加し、既存のキーのために、セットヘッダすることができ、追加の値の配列を追加し,,設定した値は、値のための直接交換です。それAPPENDと割り当ての違い。
JSONの
データ要求は、同じデータに応答してもJSONであってもよい、JSONであってもよいです。安らかなスタイルのAPI JSON形式のデータが返されます。JSON文字列要求は応答がJSON文字列をエンコードされ、デコードされ、Goが標準ライブラリのエンコーディング/ JSONを提供します
type Post struct {
User string
Threads []string
}
func indexHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
post := &Post{
User: "vanyar",
Threads: []string{"first", "second", "third"},
}
json, _ := json.Marshal(post)
w.Write(json)
}
☁ ~ curl -i http://127.0.0.1:8000/
HTTP/1.1 200 OK
Content-Type: application/json
Date: Thu, 08 Dec 2016 06:45:17 GMT
Content-Length: 54
{"User":"vanyar","Threads":["first","second","third"]}%
もちろん、契約の詳細は後にこれを行うJSON。
概要
Webアプリケーションのためには、応答は、基本的な内容に返され、要求を処理します。golangもリクエストをカプセル化し、ReponseWriterを開発することでした。要求又は応答するかどうか、URL、ヘッダとボディ関連のデータのために処理されます。httpプロトコルの基本的な内容。
体を処理し、時々、ヘッダ内のプロセスデータに必要なデータに加えて、一般的な例は、治療クッキーです。このトピックでは、クッキーに説明します。