mirror of
https://github.com/donl/gPanel.git
synced 2026-06-30 06:12:06 -06:00
Merge pull request #68 from george-e-shaw-iv/master
Logging API Completed, Graceful Shutdown Fixed
This commit is contained in:
commit
71411191b2
19 changed files with 445 additions and 99 deletions
8
.gitignore
vendored
8
.gitignore
vendored
|
|
@ -1,7 +1,11 @@
|
|||
# Ignore executables generated
|
||||
main
|
||||
|
||||
gpanel
|
||||
|
||||
# Ignore database files
|
||||
datastore.db
|
||||
datastore.db.lock
|
||||
|
||||
datastore.db.lock
|
||||
# Ignore log files
|
||||
logs/*
|
||||
!logs/README.md
|
||||
|
|
|
|||
|
|
@ -27,3 +27,9 @@ body {
|
|||
cursor:pointer;
|
||||
}
|
||||
/* Navbar End */
|
||||
|
||||
/* General Start */
|
||||
.btn {
|
||||
cursor:pointer;
|
||||
}
|
||||
/* General End */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
var logModal = jQuery('.view-log-modal');
|
||||
|
||||
jQuery('._js_diagnostics-clear-log').on('click', function(e){
|
||||
e.preventDefault();
|
||||
|
||||
var logName = jQuery(this).attr('data');
|
||||
|
||||
var title;
|
||||
switch(logName) {
|
||||
case "client_errors":
|
||||
title = "Client Error Log (4xx)";
|
||||
break;
|
||||
case "server_errors":
|
||||
title = "Server Error Log (5xx)";
|
||||
break;
|
||||
case "load_time":
|
||||
title = "Load Time Log";
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
var ensure = confirm('Are you sure you want to clear ' + title + '?');
|
||||
if (ensure) {
|
||||
var requestData = {};
|
||||
requestData["name"] = logName+".log";
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('UPDATE', 'api/logs/delete', true);
|
||||
xhr.send(JSON.stringify(requestData));
|
||||
|
||||
xhr.onloadend = function() {
|
||||
if(xhr.status == 204) {
|
||||
jQuery(logModal).find('.modal-body textarea').html('The log is currently empty.');
|
||||
}
|
||||
else {
|
||||
if(xhr.response != undefined && xhr.response.length != 0) {
|
||||
alert(xhr.response);
|
||||
}
|
||||
else {
|
||||
alert("An error has occurred, please contact your webhost administrator.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
var logModal = jQuery('.view-log-modal');
|
||||
|
||||
jQuery('._js_diagnostics-view-log').on('click', function(e){
|
||||
e.preventDefault();
|
||||
|
||||
var logName = jQuery(this).attr('data');
|
||||
|
||||
var title;
|
||||
switch(logName) {
|
||||
case "client_errors":
|
||||
title = "Client Error Log (4xx)";
|
||||
break;
|
||||
case "server_errors":
|
||||
title = "Server Error Log (5xx)";
|
||||
break;
|
||||
case "load_time":
|
||||
title = "Load Time Log";
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
jQuery(logModal).find('.modal-title').html(title);
|
||||
jQuery(logModal).find('._js_diagnostics-clear-log').attr('data', logName);
|
||||
|
||||
var requestData = {};
|
||||
requestData["name"] = logName+".log";
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', 'api/logs/read', true);
|
||||
xhr.send(JSON.stringify(requestData));
|
||||
|
||||
xhr.onloadend = function() {
|
||||
if(xhr.status == 200) {
|
||||
var responseData;
|
||||
|
||||
if(xhr.response != undefined && xhr.response.length != 0) {
|
||||
responseData = xhr.response;
|
||||
}
|
||||
else {
|
||||
responseData = "The log is currently empty."
|
||||
}
|
||||
|
||||
jQuery(logModal).find('.modal-body textarea').html(responseData);
|
||||
jQuery(logModal).modal('show');
|
||||
}
|
||||
else {
|
||||
if(xhr.response != undefined && xhr.response.length != 0) {
|
||||
alert(xhr.response);
|
||||
}
|
||||
else {
|
||||
alert('An error has occurred, please contact your webhost administrator.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
|
@ -27,6 +27,26 @@
|
|||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="modal fade view-log-modal" tabindex="-1" role="dialog" aria-labelledby="view-log-modal" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"></h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<textarea class="w-100 h-100" readonly></textarea>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||
<button type="button" class="btn btn-danger _js_diagnostics-clear-log" data="">Clear Log</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
|
|
@ -47,6 +67,20 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-5">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title">Diagnostics</h4>
|
||||
<h6 class="card-subtitle mb-4 text-muted">View various server data pools that may help pinpoint issues</h6>
|
||||
<button type="button" class="btn btn-outline-primary _js_diagnostics-view-log" data="client_errors">Client Error Log</button>
|
||||
<button type="button" class="btn btn-outline-primary _js_diagnostics-view-log" data="server_errors">Server Error Log</button>
|
||||
<button type="button" class="btn btn-outline-primary _js_diagnostics-view-log" data="load_time">Load Time Log</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="sticky-footer">
|
||||
|
|
@ -75,6 +109,9 @@
|
|||
<script type="text/javascript" src="assets/js/panelHandlers/publicServer/start.js"></script>
|
||||
<script type="text/javascript" src="assets/js/panelHandlers/publicServer/shutdown.js"></script>
|
||||
<script type="text/javascript" src="assets/js/panelHandlers/publicServer/restart.js"></script>
|
||||
|
||||
<script type="text/javascript" src="assets/js/panelHandlers/diagnostics/viewLog.js"></script>
|
||||
<script type="text/javascript" src="assets/js/panelHandlers/diagnostics/deleteLog.js"></script>
|
||||
<!-- KEEP AT BOTTOM OF BODY TAGS -->
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
8
logs/README.md
Normal file
8
logs/README.md
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# gPanel Logs
|
||||
|
||||
The actual log files are ignored by the .gitignore file. They are generated automatically upon being needed within the software itself.
|
||||
|
||||
Current log files:
|
||||
- client_errors.log
|
||||
- server_errors.log
|
||||
- loadtime.log
|
||||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/Ennovar/gPanel/pkg/api/logs"
|
||||
"github.com/Ennovar/gPanel/pkg/api/server"
|
||||
"github.com/Ennovar/gPanel/pkg/api/user"
|
||||
"github.com/Ennovar/gPanel/pkg/public"
|
||||
|
|
@ -39,6 +40,10 @@ func HandleAPI(res http.ResponseWriter, req *http.Request, path string, publicSe
|
|||
return true, server.Restart(res, req, publicServer)
|
||||
case "/server/maintenance":
|
||||
return true, server.Maintenance(res, req, publicServer)
|
||||
case "/logs/read":
|
||||
return true, logs.Read(res, req)
|
||||
case "/logs/delete":
|
||||
return true, logs.Delete(res, req)
|
||||
default:
|
||||
return false, false
|
||||
}
|
||||
|
|
|
|||
55
pkg/api/logs/delete.go
Normal file
55
pkg/api/logs/delete.go
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
// Package logs is a child of package api to handle api calls concerning log files
|
||||
package logs
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/Ennovar/gPanel/pkg/file"
|
||||
)
|
||||
|
||||
func Delete(res http.ResponseWriter, req *http.Request) bool {
|
||||
if req.Method != "UPDATE" {
|
||||
http.Error(res, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
|
||||
return false
|
||||
}
|
||||
|
||||
var deleteLogRequestData struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
err := json.NewDecoder(req.Body).Decode(&deleteLogRequestData)
|
||||
if err != nil {
|
||||
http.Error(res, err.Error(), http.StatusBadRequest)
|
||||
return false
|
||||
}
|
||||
|
||||
valid := false
|
||||
for _, log := range file.KNOWN_LOGS {
|
||||
if log == deleteLogRequestData.Name {
|
||||
valid = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !valid {
|
||||
http.Error(res, "Attempting to delete an unknown log file.", http.StatusBadRequest)
|
||||
return false
|
||||
}
|
||||
|
||||
handle, err := file.Open(deleteLogRequestData.Name, true, true)
|
||||
if err != nil {
|
||||
http.Error(res, err.Error(), http.StatusBadRequest)
|
||||
return false
|
||||
}
|
||||
|
||||
closeErr, deleteErr := handle.Close(true)
|
||||
if closeErr != nil || deleteErr != nil {
|
||||
http.Error(res, closeErr.Error()+" AND "+deleteErr.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
|
||||
res.WriteHeader(http.StatusNoContent)
|
||||
|
||||
return true
|
||||
}
|
||||
57
pkg/api/logs/read.go
Normal file
57
pkg/api/logs/read.go
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
// Package logs is a child of package api to handle api calls concerning log files
|
||||
package logs
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/Ennovar/gPanel/pkg/file"
|
||||
)
|
||||
|
||||
func Read(res http.ResponseWriter, req *http.Request) bool {
|
||||
if req.Method != "POST" {
|
||||
http.Error(res, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
|
||||
return false
|
||||
}
|
||||
|
||||
var readLogRequestData struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
err := json.NewDecoder(req.Body).Decode(&readLogRequestData)
|
||||
if err != nil {
|
||||
http.Error(res, err.Error(), http.StatusBadRequest)
|
||||
return false
|
||||
}
|
||||
|
||||
valid := false
|
||||
for _, log := range file.KNOWN_LOGS {
|
||||
if log == readLogRequestData.Name {
|
||||
valid = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !valid {
|
||||
http.Error(res, "Attempting to read from an unknown log file.", http.StatusBadRequest)
|
||||
return false
|
||||
}
|
||||
|
||||
handle, err := file.Open(readLogRequestData.Name, true, true)
|
||||
if err != nil {
|
||||
http.Error(res, err.Error(), http.StatusBadRequest)
|
||||
return false
|
||||
}
|
||||
defer handle.Close(false)
|
||||
|
||||
data, err := handle.Read()
|
||||
if err != nil {
|
||||
http.Error(res, err.Error(), http.StatusBadRequest)
|
||||
return false
|
||||
}
|
||||
|
||||
res.WriteHeader(http.StatusOK)
|
||||
res.Write(data)
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@ func Shutdown(res http.ResponseWriter, req *http.Request, publicServer *public.C
|
|||
}
|
||||
|
||||
var shutdownRequestData struct {
|
||||
graceful bool `json:"graceful"`
|
||||
Graceful bool `json:"graceful"`
|
||||
}
|
||||
|
||||
err := json.NewDecoder(req.Body).Decode(&shutdownRequestData)
|
||||
|
|
@ -24,7 +24,7 @@ func Shutdown(res http.ResponseWriter, req *http.Request, publicServer *public.C
|
|||
return false
|
||||
}
|
||||
|
||||
err = publicServer.Stop(shutdownRequestData.graceful)
|
||||
err = publicServer.Stop(shutdownRequestData.Graceful)
|
||||
if err != nil {
|
||||
http.Error(res, err.Error(), http.StatusBadRequest)
|
||||
return false
|
||||
|
|
|
|||
123
pkg/file/file.go
Normal file
123
pkg/file/file.go
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
// Package file handles various file operations
|
||||
package file
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
const (
|
||||
LOG_CLIENT_ERRORS = "client_errors.log"
|
||||
LOG_SERVER_ERRORS = "server_errors.log"
|
||||
LOG_LOADTIME = "load_time.log"
|
||||
)
|
||||
|
||||
var KNOWN_LOGS = [...]string{LOG_CLIENT_ERRORS, LOG_SERVER_ERRORS, LOG_LOADTIME}
|
||||
|
||||
type Handler struct {
|
||||
fileHandle *os.File
|
||||
path string
|
||||
append bool
|
||||
}
|
||||
|
||||
func Open(file string, append bool, log bool) (*Handler, error) {
|
||||
var err error
|
||||
var absPath string
|
||||
var f *os.File
|
||||
|
||||
// Generate file path
|
||||
if log {
|
||||
absPath, err = filepath.Abs("logs/" + file)
|
||||
} else {
|
||||
absPath, err = filepath.Abs(file)
|
||||
}
|
||||
|
||||
// Handle file path errors
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Open file
|
||||
if append {
|
||||
f, err = os.OpenFile(absPath, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644)
|
||||
} else {
|
||||
f, err = os.OpenFile(absPath, os.O_TRUNC|os.O_CREATE|os.O_RDWR, 0644)
|
||||
}
|
||||
|
||||
//Handle open file errors
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Upon success, return the handler
|
||||
return &Handler{
|
||||
fileHandle: f,
|
||||
path: absPath,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (h *Handler) checkExistence(createIfNotExist bool) (bool, error) {
|
||||
if _, err := os.Stat(h.path); os.IsNotExist(err) {
|
||||
if createIfNotExist {
|
||||
if h.append {
|
||||
h.fileHandle, err = os.OpenFile(h.path, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644)
|
||||
} else {
|
||||
h.fileHandle, err = os.OpenFile(h.path, os.O_TRUNC|os.O_CREATE|os.O_RDWR, 0644)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return false, nil
|
||||
} else {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (h *Handler) Read() ([]byte, error) {
|
||||
_, err := h.checkExistence(true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadAll(h.fileHandle)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return data, err
|
||||
}
|
||||
|
||||
func (h *Handler) Write(data string) (int, error) {
|
||||
_, err := h.checkExistence(true)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
written, err := h.fileHandle.Write([]byte(data + "\n"))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return written, err
|
||||
}
|
||||
|
||||
func (h *Handler) Close(delete bool) (error, error) {
|
||||
exist, _ := h.checkExistence(false)
|
||||
if !exist {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
closeErr := h.fileHandle.Close()
|
||||
|
||||
if delete {
|
||||
deleteErr := os.Remove(h.path)
|
||||
return closeErr, deleteErr
|
||||
}
|
||||
|
||||
return closeErr, nil
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
// Package logging handles the various mediums and logic of logging messages and reports.
|
||||
package logging
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/Ennovar/gPanel/pkg/networking"
|
||||
)
|
||||
|
||||
const (
|
||||
PRIVATE_PREFIX = "PRIVATE::"
|
||||
PUBLIC_PREFIX = "PUBLIC::"
|
||||
|
||||
NORMAL_LOG = 1
|
||||
FATAL_LOG = 2
|
||||
)
|
||||
|
||||
// Console logs a prefix, IP, and message all appeneded together to the console.
|
||||
func Console(prefix string, logType int, msg string) {
|
||||
rawClientIP, _ := networking.GetClientIP()
|
||||
clientIP := strings.TrimSpace(string(rawClientIP))
|
||||
|
||||
msg = prefix + clientIP + "::" + msg
|
||||
|
||||
switch logType {
|
||||
default:
|
||||
fallthrough
|
||||
case 1:
|
||||
log.Println(msg)
|
||||
case 2:
|
||||
log.Fatal(msg)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
// Package logging handles the various mediums and logic of logging messages and reports.
|
||||
package logging
|
||||
|
||||
import "os"
|
||||
|
||||
const (
|
||||
PRIVATE_LOG_FOLDER = "logs/private/"
|
||||
PUBLIC_LOG_FOLDER = "logs/public/"
|
||||
|
||||
ERROR = "error.log"
|
||||
WARNING = "warning.log"
|
||||
)
|
||||
|
||||
// File logs a given message to a log file
|
||||
func File(logFolder string, logFile string, msg string) (string, error) {
|
||||
msg += "\n"
|
||||
|
||||
f, err := os.OpenFile(logFolder+logFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
} else {
|
||||
writtenBytes, err := f.Write([]byte(msg))
|
||||
|
||||
if err != nil {
|
||||
return string(writtenBytes), err
|
||||
} else {
|
||||
err := f.Close()
|
||||
|
||||
if err != nil {
|
||||
return string(writtenBytes), err
|
||||
} else {
|
||||
return string(writtenBytes), nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -8,9 +8,10 @@ import (
|
|||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/Ennovar/gPanel/pkg/logging"
|
||||
"github.com/Ennovar/gPanel/pkg/file"
|
||||
"github.com/Ennovar/gPanel/pkg/routing"
|
||||
)
|
||||
|
||||
|
|
@ -18,6 +19,9 @@ type Controller struct {
|
|||
Directory string
|
||||
GracefulShutdownTimeout time.Duration
|
||||
Status int
|
||||
ClientLogger *file.Handler
|
||||
ServerLogger *file.Handler
|
||||
LoadTimeLogger *file.Handler
|
||||
}
|
||||
|
||||
var controller Controller
|
||||
|
|
@ -25,10 +29,17 @@ var server http.Server
|
|||
|
||||
// New function returns a new PublicWeb type.
|
||||
func New() *Controller {
|
||||
clientLogHandler, _ := file.Open(file.LOG_CLIENT_ERRORS, true, true)
|
||||
serverLogHandler, _ := file.Open(file.LOG_CLIENT_ERRORS, true, true)
|
||||
loadLogHandler, _ := file.Open(file.LOG_LOADTIME, true, true)
|
||||
|
||||
controller = Controller{
|
||||
Directory: "document_roots/public/",
|
||||
GracefulShutdownTimeout: 5 * time.Second,
|
||||
Status: 0,
|
||||
ClientLogger: clientLogHandler,
|
||||
ServerLogger: serverLogHandler,
|
||||
LoadTimeLogger: loadLogHandler,
|
||||
}
|
||||
|
||||
server = http.Server{
|
||||
|
|
@ -60,18 +71,14 @@ func (con *Controller) Stop(graceful bool) error {
|
|||
defer cancel()
|
||||
|
||||
err := server.Shutdown(context)
|
||||
if err != nil {
|
||||
fmt.Printf("Graceful shutdown failed attempting forced: %v\n", err)
|
||||
|
||||
err = server.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
fmt.Printf("Graceful shutdown failed attempting forced: %v\n", err)
|
||||
}
|
||||
|
||||
err := server.Close()
|
||||
if err != nil {
|
||||
if err := server.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -116,6 +123,8 @@ func (con *Controller) Maintenance() {
|
|||
// ServeHTTP function routes all requests for the public web server. It is used in the main
|
||||
// function inside of the http.ListenAndServe() function for the public host.
|
||||
func (con *Controller) ServeHTTP(res http.ResponseWriter, req *http.Request) {
|
||||
startTime := time.Now()
|
||||
|
||||
switch con.Status {
|
||||
case 0: // This will actually never show because this function won't run if the server is off
|
||||
http.Error(res, "The server is currently down and not serving requests.", http.StatusServiceUnavailable)
|
||||
|
|
@ -140,16 +149,16 @@ func (con *Controller) ServeHTTP(res http.ResponseWriter, req *http.Request) {
|
|||
f, err := os.Open(path)
|
||||
|
||||
if err != nil {
|
||||
con.ClientLogger.Write(path + "::" + strconv.Itoa(http.StatusNotFound) + "::" + err.Error())
|
||||
routing.HttpThrowStatus(http.StatusNotFound, res)
|
||||
logging.Console(logging.PUBLIC_PREFIX, logging.NORMAL_LOG, "Path \""+path+"\" rendered a 404 error.")
|
||||
return
|
||||
}
|
||||
|
||||
contentType, err := routing.GetContentType(path)
|
||||
|
||||
if err != nil {
|
||||
con.ClientLogger.Write(path + "::" + strconv.Itoa(http.StatusUnsupportedMediaType) + "::" + err.Error())
|
||||
routing.HttpThrowStatus(http.StatusUnsupportedMediaType, res)
|
||||
logging.Console(logging.PUBLIC_PREFIX, logging.NORMAL_LOG, "Path \""+path+"\" content type could not be determined, 404 error.")
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -157,8 +166,11 @@ func (con *Controller) ServeHTTP(res http.ResponseWriter, req *http.Request) {
|
|||
_, err = io.Copy(res, f)
|
||||
|
||||
if err != nil {
|
||||
con.ServerLogger.Write(path + "::" + strconv.Itoa(http.StatusInternalServerError) + "::" + err.Error())
|
||||
routing.HttpThrowStatus(http.StatusInternalServerError, res)
|
||||
logging.Console(logging.PUBLIC_PREFIX, logging.NORMAL_LOG, "Path \""+path+"\" rendered a 500 error.")
|
||||
return
|
||||
}
|
||||
|
||||
elapsedTime := time.Since(startTime)
|
||||
con.LoadTimeLogger.Write(path + " rendered in " + strconv.FormatFloat(elapsedTime.Seconds(), 'f', 6, 64) + " seconds")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,23 +5,28 @@ import (
|
|||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/Ennovar/gPanel/pkg/api"
|
||||
"github.com/Ennovar/gPanel/pkg/logging"
|
||||
"github.com/Ennovar/gPanel/pkg/file"
|
||||
"github.com/Ennovar/gPanel/pkg/public"
|
||||
"github.com/Ennovar/gPanel/pkg/routing"
|
||||
)
|
||||
|
||||
type Controller struct {
|
||||
Directory string
|
||||
Public *public.Controller
|
||||
Directory string
|
||||
Public *public.Controller
|
||||
ServerLogger *file.Handler
|
||||
}
|
||||
|
||||
// New returns a new PrivateHost type.
|
||||
func New() Controller {
|
||||
serverErrorLogger, _ := file.Open(file.LOG_SERVER_ERRORS, true, true)
|
||||
|
||||
return Controller{
|
||||
Directory: "document_roots/webhost/",
|
||||
Public: public.New(),
|
||||
Directory: "document_roots/webhost/",
|
||||
Public: public.New(),
|
||||
ServerLogger: serverErrorLogger,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -37,6 +42,7 @@ func (con *Controller) ServeHTTP(res http.ResponseWriter, req *http.Request) {
|
|||
|
||||
if reqAuth(path) {
|
||||
if !checkAuth(res, req) {
|
||||
con.ServerLogger.Write(path + "::" + strconv.Itoa(http.StatusUnauthorized) + "::" + http.StatusText(http.StatusUnauthorized))
|
||||
http.Error(res, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
|
@ -52,16 +58,16 @@ func (con *Controller) ServeHTTP(res http.ResponseWriter, req *http.Request) {
|
|||
f, err := os.Open(path)
|
||||
|
||||
if err != nil {
|
||||
con.ServerLogger.Write(path + "::" + strconv.Itoa(http.StatusNotFound) + "::" + err.Error())
|
||||
routing.HttpThrowStatus(http.StatusNotFound, res)
|
||||
logging.Console(logging.PRIVATE_PREFIX, logging.NORMAL_LOG, "Path \""+path+"\" rendered a 404 error.")
|
||||
return
|
||||
}
|
||||
|
||||
contentType, err := routing.GetContentType(path)
|
||||
|
||||
if err != nil {
|
||||
con.ServerLogger.Write(path + "::" + strconv.Itoa(http.StatusUnsupportedMediaType) + "::" + err.Error())
|
||||
routing.HttpThrowStatus(http.StatusUnsupportedMediaType, res)
|
||||
logging.Console(logging.PUBLIC_PREFIX, logging.NORMAL_LOG, "Path \""+path+"\" content type could not be determined, 404 error.")
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -69,8 +75,8 @@ func (con *Controller) ServeHTTP(res http.ResponseWriter, req *http.Request) {
|
|||
_, err = io.Copy(res, f)
|
||||
|
||||
if err != nil {
|
||||
con.ServerLogger.Write(path + "::" + strconv.Itoa(http.StatusInternalServerError) + "::" + err.Error())
|
||||
routing.HttpThrowStatus(http.StatusInternalServerError, res)
|
||||
logging.Console(logging.PUBLIC_PREFIX, logging.NORMAL_LOG, "Path \""+path+"\" rendered a 500 error.")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue