github.com/goplus/yap@v0.8.1/context.go (about) 1 /* 2 * Copyright (c) 2023 The GoPlus Authors (goplus.org). All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package yap 18 19 import ( 20 "encoding/json" 21 "io" 22 "log" 23 "net/http" 24 "strconv" 25 "strings" 26 ) 27 28 type Context struct { 29 *http.Request 30 http.ResponseWriter 31 32 engine *Engine 33 } 34 35 func (p *Context) setParam(name, val string) { 36 p.ParseForm() 37 p.Form.Set(name, val) 38 } 39 40 // Gop_Env returns the value associated with the name. 41 // If the name exists in URL query, it returns the first value for the name. 42 func (p *Context) Gop_Env(name string) string { 43 return p.Param(name) 44 } 45 46 // Param returns the value associated with the name. 47 // If the name exists in URL query, it returns the first value for the name. 48 func (p *Context) Param(name string) string { 49 return p.FormValue(name) 50 } 51 52 func (p *Context) ParamInt(name string, defval int) int { 53 ret := p.Param(name) 54 if ret != "" { 55 if v, err := strconv.Atoi(ret); err == nil { 56 return v 57 } 58 } 59 return defval 60 } 61 62 // Accept header specifies: 63 // Accept: <MIME_type>/<MIME_subtype> 64 // Accept: <MIME_type>/* 65 // Accept: */* 66 // Multiple types, weighted with the quality value syntax: 67 // Accept: text/html, application/xhtml+xml, application/xml;q=0.9, image/webp, */*;q=0.8 68 // FIXME: 1. quality value not supported, 2. don't need parse all, just find the first match with a spliter iterator 69 func (p *Context) Accept(mime ...string) string { 70 accept := p.Request.Header.Get("Accept") 71 for _, m := range mime { 72 if acceptMime(accept, m) { 73 return m 74 } 75 } 76 return "" 77 } 78 79 func acceptMime(accept string, mime string) bool { 80 for accept != "" { 81 item, left := acceptNext(accept) 82 if item == mime || (strings.HasPrefix(item, mime) && item[len(mime)] == ';') { 83 return true 84 } 85 accept = left 86 } 87 return false 88 } 89 90 func acceptNext(accept string) (item, left string) { 91 item = strings.TrimLeft(accept, " ") 92 if before, after, found := strings.Cut(item, ","); found { 93 return before, after 94 } 95 left = "" 96 return 97 } 98 99 // Redirect replies to the request with a redirect to url, 100 // which may be a path relative to the request path. 101 func (p *Context) Redirect(url string, code ...int) { 102 statusCode := http.StatusFound 103 if code != nil { 104 statusCode = code[0] 105 } 106 http.Redirect(p.ResponseWriter, p.Request, url, statusCode) 107 } 108 109 func (p *Context) TEXT(code int, mime string, text string) { 110 w := p.ResponseWriter 111 h := w.Header() 112 h.Set("Content-Length", strconv.Itoa(len(text))) 113 h.Set("Content-Type", mime) 114 w.WriteHeader(code) 115 io.WriteString(w, text) 116 } 117 118 func (p *Context) DATA(code int, mime string, data []byte) { 119 w := p.ResponseWriter 120 h := w.Header() 121 h.Set("Content-Length", strconv.Itoa(len(data))) 122 h.Set("Content-Type", mime) 123 w.WriteHeader(code) 124 w.Write(data) 125 } 126 127 func (p *Context) PrettyJSON(code int, data interface{}) { 128 msg, err := json.MarshalIndent(data, "", " ") 129 if err != nil { 130 panic(err) 131 } 132 p.DATA(code, "application/json", msg) 133 } 134 135 func (p *Context) JSON(code int, data interface{}) { 136 msg, err := json.Marshal(data) 137 if err != nil { 138 panic(err) 139 } 140 p.DATA(code, "application/json", msg) 141 } 142 143 func (p *Context) YAP(code int, yapFile string, data interface{}) { 144 w := p.ResponseWriter 145 t := p.engine.templ(yapFile) 146 if t == nil { 147 log.Panicln("YAP: not find template:", yapFile) 148 } 149 h := w.Header() 150 h.Set("Content-Type", "text/html") 151 err := t.Execute(w, data) 152 if err != nil { 153 log.Panicln("YAP:", err) 154 } 155 }