BUGFIX: Content-Type, Nil Raw Body Edge Case, Links
FIXES: * There was an edge case where a raw body for HTML would potentially result in a nil byte slice exception. This has been fixed. (I don't even know if it was possible, I just made sure it wasn't.) * The links browser is now explicitly returned as HTML and properly detected as a "browser". * Hyperlinks for links, w3m added to Usage page. * Content-Type is now always set correctly; there were cases where it was improperly returning e.g. text/plain for JSON.
This commit is contained in:
parent
8a0465a0f4
commit
6b75e17f48
20
README.adoc
Normal file
20
README.adoc
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
= ClientInfo
|
||||||
|
r00t^2 <brent.saner@gmail.com>
|
||||||
|
Last rendered {localdatetime}
|
||||||
|
:doctype: book
|
||||||
|
:docinfo: shared
|
||||||
|
:data-uri:
|
||||||
|
:imagesdir: images
|
||||||
|
:sectlinks:
|
||||||
|
:sectnums:
|
||||||
|
:sectnumlevels: 7
|
||||||
|
:toc: preamble
|
||||||
|
:toc2: left
|
||||||
|
:idprefix:
|
||||||
|
:toclevels: 7
|
||||||
|
//:toclevels: 4
|
||||||
|
:source-highlighter: rouge
|
||||||
|
:docinfo: shared
|
||||||
|
|
||||||
|
== DOCS
|
||||||
|
**TODO!**
|
8
TODO
8
TODO
@ -1,3 +1,7 @@
|
|||||||
- suggest browser, OS alternatives (again)
|
- suggest browser, OS alternatives (again)
|
||||||
- link to ipinfo.io for client IP (again)
|
- implement ipinfo.io equiv. myself?
|
||||||
-- or just implement myself
|
- also link to https://www.useragentstring.com/
|
||||||
|
-- or maybe https://www.whatsmyua.info/
|
||||||
|
-- see https://www.useragentstring.com/pages/api.php
|
||||||
|
- note that though lynx and elinks are "graphical", links is considered text. w3m is considered graphical.
|
||||||
|
- fix the text/plain issue for the json (et. al.) renderer
|
||||||
|
@ -79,10 +79,15 @@ var (
|
|||||||
mediaJSON: json.MarshalIndent,
|
mediaJSON: json.MarshalIndent,
|
||||||
mediaXML: xml.MarshalIndent,
|
mediaXML: xml.MarshalIndent,
|
||||||
}
|
}
|
||||||
|
// valid MIMEs.
|
||||||
okAcceptMime []string = []string{
|
okAcceptMime []string = []string{
|
||||||
mediaJSON,
|
mediaJSON,
|
||||||
mediaXML,
|
mediaXML,
|
||||||
mediaYAML,
|
mediaYAML,
|
||||||
mediaHTML,
|
mediaHTML,
|
||||||
}
|
}
|
||||||
|
// These are actually HTML.
|
||||||
|
htmlOverride map[string]bool = map[string]bool{
|
||||||
|
"Links": true,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
@ -19,6 +19,7 @@ import (
|
|||||||
sysd "github.com/coreos/go-systemd/daemon"
|
sysd "github.com/coreos/go-systemd/daemon"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
`github.com/goccy/go-yaml`
|
`github.com/goccy/go-yaml`
|
||||||
|
`r00t2.io/clientinfo/version`
|
||||||
"r00t2.io/goutils/multierr"
|
"r00t2.io/goutils/multierr"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -280,6 +281,8 @@ func (s *Server) handleDefault(resp http.ResponseWriter, req *http.Request) {
|
|||||||
|
|
||||||
s.log.Debug("server.Server.handleDefault: Handling request:\n%s", spew.Sdump(req))
|
s.log.Debug("server.Server.handleDefault: Handling request:\n%s", spew.Sdump(req))
|
||||||
|
|
||||||
|
resp.Header().Set("ClientInfo-Version", version.Ver.Short())
|
||||||
|
|
||||||
page = &Page{
|
page = &Page{
|
||||||
Info: &R00tInfo{
|
Info: &R00tInfo{
|
||||||
Client: nil,
|
Client: nil,
|
||||||
@ -327,6 +330,9 @@ func (s *Server) handleDefault(resp http.ResponseWriter, req *http.Request) {
|
|||||||
http.Error(resp, fmt.Sprintf("ERROR: Failed to parse 'User-Agent' '%s'", ua), http.StatusInternalServerError)
|
http.Error(resp, fmt.Sprintf("ERROR: Failed to parse 'User-Agent' '%s'", ua), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if parsedUA.Name != nil && htmlOverride[*parsedUA.Name] {
|
||||||
|
parsedUA.IsDesktop = true
|
||||||
|
}
|
||||||
page.Info.Client = append(page.Info.Client, parsedUA)
|
page.Info.Client = append(page.Info.Client, parsedUA)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -470,6 +476,7 @@ func (s *Server) handleAbout(resp http.ResponseWriter, req *http.Request) {
|
|||||||
|
|
||||||
s.log.Debug("server.Server.handleAbout: Handling request:\n%s", spew.Sdump(req))
|
s.log.Debug("server.Server.handleAbout: Handling request:\n%s", spew.Sdump(req))
|
||||||
|
|
||||||
|
resp.Header().Set("ClientInfo-Version", version.Ver.Short())
|
||||||
resp.Header().Set("Content-Type", "text/html; charset=utf-8")
|
resp.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
|
|
||||||
if err = tpl.ExecuteTemplate(resp, "about", renderPage); err != nil {
|
if err = tpl.ExecuteTemplate(resp, "about", renderPage); err != nil {
|
||||||
@ -495,7 +502,9 @@ func (s *Server) handleUsage(resp http.ResponseWriter, req *http.Request) {
|
|||||||
|
|
||||||
s.log.Debug("server.Server.handleUsage: Handling request:\n%s", spew.Sdump(req))
|
s.log.Debug("server.Server.handleUsage: Handling request:\n%s", spew.Sdump(req))
|
||||||
|
|
||||||
|
resp.Header().Set("ClientInfo-Version", version.Ver.Short())
|
||||||
resp.Header().Set("Content-Type", "text/html; charset=utf-8")
|
resp.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
|
|
||||||
if err = tpl.ExecuteTemplate(resp, "usage", renderPage); err != nil {
|
if err = tpl.ExecuteTemplate(resp, "usage", renderPage); err != nil {
|
||||||
s.log.Err("server.Server.handleAbout: Failed to execute template for '%s': %v", req.RemoteAddr, err)
|
s.log.Err("server.Server.handleAbout: Failed to execute template for '%s': %v", req.RemoteAddr, err)
|
||||||
http.Error(resp, "ERROR: Failed to render HTML", http.StatusInternalServerError)
|
http.Error(resp, "ERROR: Failed to render HTML", http.StatusInternalServerError)
|
||||||
@ -511,6 +520,8 @@ func (s *Server) renderJSON(page *Page, resp http.ResponseWriter) (err error) {
|
|||||||
|
|
||||||
var b []byte
|
var b []byte
|
||||||
|
|
||||||
|
resp.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
if page.DoIndent {
|
if page.DoIndent {
|
||||||
if b, err = json.MarshalIndent(page.Info, "", page.Indent); err != nil {
|
if b, err = json.MarshalIndent(page.Info, "", page.Indent); err != nil {
|
||||||
s.log.Err("server.Server.renderJSON: Failed to render to indented JSON: %v", err)
|
s.log.Err("server.Server.renderJSON: Failed to render to indented JSON: %v", err)
|
||||||
@ -561,10 +572,14 @@ func (s *Server) renderHTML(page *Page, resp http.ResponseWriter) (err error) {
|
|||||||
s.log.Err("server.Server.renderHTML: Failed to render to '%s': %v", *page.RawFmt, err)
|
s.log.Err("server.Server.renderHTML: Failed to render to '%s': %v", *page.RawFmt, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
page.Raw = new(string)
|
if b != nil {
|
||||||
*page.Raw = string(b)
|
page.Raw = new(string)
|
||||||
|
*page.Raw = string(b)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resp.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
|
|
||||||
if err = tpl.ExecuteTemplate(resp, "index", page); err != nil {
|
if err = tpl.ExecuteTemplate(resp, "index", page); err != nil {
|
||||||
s.log.Err("server.Server.renderHTML: Failed to render template: %v", err)
|
s.log.Err("server.Server.renderHTML: Failed to render template: %v", err)
|
||||||
http.Error(resp, "ERROR: Failed to render HTML", http.StatusInternalServerError)
|
http.Error(resp, "ERROR: Failed to render HTML", http.StatusInternalServerError)
|
||||||
@ -591,6 +606,9 @@ func (s *Server) renderXML(page *Page, resp http.ResponseWriter) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resp.Header().Set("Content-Type", "application/xml; charset=utf-8")
|
||||||
|
|
||||||
if _, err = resp.Write(b); err != nil {
|
if _, err = resp.Write(b); err != nil {
|
||||||
s.log.Err("server.Server.renderXML: Failed to send XML: %v", err)
|
s.log.Err("server.Server.renderXML: Failed to send XML: %v", err)
|
||||||
return
|
return
|
||||||
@ -609,6 +627,8 @@ func (s *Server) renderYML(page *Page, resp http.ResponseWriter) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resp.Header().Set("Content-Type", "application/yaml")
|
||||||
|
|
||||||
if _, err = resp.Write(b); err != nil {
|
if _, err = resp.Write(b); err != nil {
|
||||||
s.log.Err("server.Server.renderJSON: Failed to send JSON: %v", err)
|
s.log.Err("server.Server.renderJSON: Failed to send JSON: %v", err)
|
||||||
return
|
return
|
||||||
|
@ -46,8 +46,8 @@ Accept: text/html
|
|||||||
</pre>
|
</pre>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
Note that <a href="https://lynx.invisible-island.net/">Lynx</a> and <a href="http://elinks.or.cz/">Elinks</a> are considered "graphical"
|
Note that <a href="http://links.twibright.com/">Links</a>a>, <a href="https://lynx.invisible-island.net/">Lynx</a>, <a href="http://elinks.or.cz/">Elinks</a>,
|
||||||
browsers by this program as they are HTML-centric.
|
and <a href="https://w3m.sourceforge.net/">W3M</a> are considered "graphical" browsers by this program as they are HTML-centric.
|
||||||
</p>
|
</p>
|
||||||
<p id="usage_params_mod">
|
<p id="usage_params_mod">
|
||||||
The following parameters control/modify behavior.<a href="#usage_params_mod">{{ $linkico }}</a>
|
The following parameters control/modify behavior.<a href="#usage_params_mod">{{ $linkico }}</a>
|
||||||
|
Loading…
Reference in New Issue
Block a user