98 lines
3.3 KiB
Go
98 lines
3.3 KiB
Go
package web
|
|
|
|
import (
|
|
_ "embed"
|
|
"golang.captainalm.com/GOPackageHeaderServer/conf"
|
|
"golang.captainalm.com/GOPackageHeaderServer/outputMeta"
|
|
"golang.captainalm.com/GOPackageHeaderServer/web/utils"
|
|
"html/template"
|
|
"io"
|
|
"mime/multipart"
|
|
"net/http"
|
|
"net/textproto"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
type PageHandler struct {
|
|
Name string
|
|
CSS string
|
|
OutputPage bool
|
|
RangeSupported bool
|
|
CacheSettings conf.CacheSettingsYaml
|
|
MetaOutput *outputMeta.PackageMetaTagOutputter
|
|
}
|
|
|
|
var startTime = time.Now()
|
|
|
|
//go:embed output-page.html
|
|
var outputPage string
|
|
|
|
var pageTemplateFuncMap = template.FuncMap{
|
|
"isNotEmpty": func(stringIn string) bool {
|
|
return stringIn != ""
|
|
},
|
|
}
|
|
|
|
func (pgh *PageHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
|
|
if request.Method == http.MethodGet || request.Method == http.MethodHead {
|
|
tmpl, err := template.New("page-handler").Funcs(pageTemplateFuncMap).Parse(outputPage)
|
|
if err != nil {
|
|
utils.WriteResponseHeaderCanWriteBody(request.Method, writer, http.StatusInternalServerError, "Page Template Parsing Failure")
|
|
return
|
|
}
|
|
tm := handlerTemplateMarshal{
|
|
PageHandler: *pgh,
|
|
RequestPath: request.URL.Path,
|
|
}
|
|
theBuffer := &utils.BufferedWriter{}
|
|
err = tmpl.Execute(theBuffer, tm)
|
|
if err != nil {
|
|
utils.WriteResponseHeaderCanWriteBody(request.Method, writer, http.StatusInternalServerError, "Page Template Execution Failure")
|
|
return
|
|
}
|
|
writer.Header().Set("Content-Length", strconv.Itoa(len(theBuffer.Data)))
|
|
writer.Header().Set("Content-Type", "text/html; charset=utf-8")
|
|
utils.SetLastModifiedHeader(writer.Header(), startTime)
|
|
utils.SetCacheHeaderWithAge(writer.Header(), pgh.CacheSettings.MaxAge, startTime)
|
|
theETag := utils.GetValueForETagUsingBufferedWriter(theBuffer)
|
|
writer.Header().Set("ETag", theETag)
|
|
if utils.ProcessSupportedPreconditionsForNext(writer, request, startTime, theETag, pgh.CacheSettings.NotModifiedResponseUsingLastModified, pgh.CacheSettings.NotModifiedResponseUsingETags) {
|
|
httpRangeParts := utils.ProcessRangePreconditions(int64(len(theBuffer.Data)), writer, request, startTime, theETag, pgh.RangeSupported)
|
|
if httpRangeParts != nil {
|
|
if len(httpRangeParts) <= 1 {
|
|
var theWriter io.Writer = writer
|
|
if len(httpRangeParts) == 1 {
|
|
theWriter = utils.NewPartialRangeWriter(theWriter, httpRangeParts[0])
|
|
}
|
|
_, _ = theWriter.Write(theBuffer.Data)
|
|
} else {
|
|
multWriter := multipart.NewWriter(writer)
|
|
writer.Header().Set("Content-Type", "multipart/byteranges; boundary="+multWriter.Boundary())
|
|
for _, currentPart := range httpRangeParts {
|
|
mimePart, err := multWriter.CreatePart(textproto.MIMEHeader{
|
|
"Content-Range": {currentPart.ToField(int64(len(theBuffer.Data)))},
|
|
"Content-Type": {"text/plain; charset=utf-8"},
|
|
})
|
|
if err != nil {
|
|
break
|
|
}
|
|
_, err = mimePart.Write(theBuffer.Data[currentPart.Start : currentPart.Start+currentPart.Length])
|
|
if err != nil {
|
|
break
|
|
}
|
|
}
|
|
_ = multWriter.Close()
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
writer.Header().Set("Allow", http.MethodOptions+", "+http.MethodGet+", "+http.MethodHead)
|
|
if request.Method == http.MethodOptions {
|
|
utils.WriteResponseHeaderCanWriteBody(request.Method, writer, http.StatusOK, "")
|
|
} else {
|
|
utils.WriteResponseHeaderCanWriteBody(request.Method, writer, http.StatusMethodNotAllowed, "")
|
|
}
|
|
}
|
|
}
|