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  }