Go 를 통해 클라이언트 요청을 받아 처리하고 응답하는 방법을 익히자.
1. Go를 이용한 요청과 응답
2. Go를 이용한 HTML 폼 처리
3. ResponseWriter를 이용해 클라이언트에게 다시 응답 보내기
1, 2 Go를 이용한 요청과 응답 및 HTML 폼 처리
- 요청 URL 필드 구조
type URL struct {
Scheme string
Opaque string // encoded opaque data
User *Userinfo // username and password information
Host string // host or host:port
Path string // path (relative paths may omit leading slash)
RawPath string // encoded path hint (see EscapedPath method)
ForceQuery bool // append a query ('?') even if RawQuery is empty
RawQuery string // encoded query values, without '?'
Fragment string // fragment for references, without '#'
}
html form을 이용한 client 요청
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html" charset="UTF-8">
<title>Go web Programming</title>
</head>
<body>
<form action="http://127.0.0.1:8080/process?hello=world&thread=123" method="post" enctype="application/x-www-form-urlencoded">
<input type="text" name="hello" value="dksshddl"/>
<input type="text" name="post" value="456"/>
<input type="submit"/>
</form>
</body>
</html>
- URL로 http://127.0.0.1:8080/process?hello=world&thread=123 을 post method로 서버에 요청
- Content-type --> application/x-wwwform-urlencoded
- 두개의 키-값 쌍을 서버로 전송 hello=dksshddl와 post=456
package main
import (
"fmt"
"net/http"
)
func process(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
fmt.Fprintln(w, r.Form)
}
func main() {
server := http.Server{
Addr: "127.0.0.1:8080",
Handler: nil,
}
http.HandleFunc("/process", process)
server.ListenAndServe()
}
- 서버에서는 request url을 parse하고, 그 Form을 출력할 수 있다.
- r.Form은 map으로 저장되기 떄문에, map[key]로 접근할 수 있다.
- post로 전송된 값 만을 가지고 오고 싶을 떄에는 r.Form -> r.PostForm으로 바꿔 접근할 수있다.
다양한 폼 및 multipart/form-data 사용
package main
import (
"fmt"
"net/http"
)
func process(w http.ResponseWriter, r *http.Request) {
r.ParseMultipartForm(1024)
fmt.Fprintln(w, "(1)", r.FormValue("hello"))
fmt.Fprintln(w, "(2)", r.Form)
fmt.Fprintln(w, "(3)", r.PostFormValue("hello"))
fmt.Fprintln(w, "(4)", r.PostForm)
fmt.Fprintln(w, "(5)", r.MultipartForm)
}
func main() {
server := http.Server{
Addr: "127.0.0.1:8080",
Handler: nil,
}
http.HandleFunc("/process", process)
server.ListenAndServe()
}
키-값 쌍 | 콘텐츠 타입 | ||||
필드 | 호출해야 할 메소드 | URL | Form | 인코딩 URL | Multipart |
Form | ParseForm | O | O | O | - |
PostForm | Form | - | O | O | - |
MultipartForm | ParseMultipartForm | - | O | - | O |
FormValue | N/A | O | O | O | - |
PostFormValue | N/A | - | O | O | - |
파일
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html" charset="UTF-8">
<title>Go web Programming</title>
</head>
<body>
<form action="http://127.0.0.1:8080/process?hello=world&thread=123" method="post" enctype="multipart/form-data">
<input type="text" name="hello" value="dksshddl"/>
<input type="text" name="post" value="456"/>
<input type="file" name="uploaded">
<input type="submit"/>
</form>
</body>
</html>
form 에 file type input 추가
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func process(w http.ResponseWriter, r *http.Request) {
r.ParseMultipartForm(1024)
fileHeader := r.MultipartForm.File["uploaded"][0]
file, err := fileHeader.Open()
if err == nil {
data, err := ioutil.ReadAll(file)
if err == nil {
fmt.Fprintln(w, string(data))
}
}
}
func main() {
server := http.Server{
Addr: "127.0.0.1:8080",
Handler: nil,
}
http.HandleFunc("/process", process)
server.ListenAndServe()
}
서버 쪽에서는 제출 된 form에서 file을 읽어낸다.
3. ResponseWriter
- 클라이언트에게 응답을 하기 위해서는 Response 구조를 작성해야 한다.
- Response내의 응답할 데이터를 설정해 주어야 한다.
- ResponseWriter는 인터페이스이며 핸들러가 HTTP 응답을 만들 때 사용
- ResponseWriter는 Write, WriteHeader, Header 메소드로 구성
Write 메소드는 바이트 배열을 취함 - Write가 호출되기까지 콘텐츠 타입이 없다면, 첫 번째 512바이트 데이터에 대한 만큼만 콘텐츠 타입으로 감지
package main
import (
"net/http"
)
func writeExample(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))
}
func main() {
server := http.Server{
Addr: "127.0.0.1:8080",
Handler: nil,
}
http.HandleFunc("/write", writeExample)
server.ListenAndServe()
}
string 데이터를 response에 작성하여 보내보자.
그 후, http 메세지를 확인해보자
linux
curl -i 127.0.0.1:8080/write
window powershell
curl -Uri 127.0.0.1:8080/wirte
WriteHeader 메소드는 응답 코드를 작성하는 것 실제 header 작성하는 부분이 아니다.
func writeHeaderExample(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(501)
fmt.Fprintln(w, "No such service, try next door")
}
window powershell 에서는 501을 에러로 출력과 함께 작성한 메세지를 출력해준다.
헤더 수정하기
func headerExample(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Location", "http://google.com")
w.WriteHeader(302)
}
응답이 들어오면, Header의 Location을 구글 사이트로 이동한다.
클라이언트에게 JSON 응답 주기
JSON 데이터 구조를 전송할 Post라는 구조 가정
type Post struct {
User string
Threads []string
}
json으로 encoding 하여 전송
func jsonExample(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
post := &Post{
User: "dksshddl",
Threads: []string{"first", "second", "third"},
}
json, _ := json.Marshal(post)
w.Write(json)
}
encoding/json 패키지의 Marshal 메소드를 이용하여 post 데이터 구조를 json 구조로 변환
Content에 json 문자열이 가지고 있는것을 확인할 수 있다.
'Language > Go' 카테고리의 다른 글
[Go] - web programming : 액션 (0) | 2020.01.16 |
---|---|
[Go] - web programming : 템플릿과 템플릿 엔진 (0) | 2020.01.15 |
[Go] - web programming : 쿠키 cookie (0) | 2020.01.06 |
[Go] - web programming : handler 기초 (0) | 2020.01.03 |
[GO] https 제공을 위한 인증된 SSL과 서버 개인 키 생성하기 (0) | 2020.01.03 |