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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 brent saner
						brent saner