complete overhaul of the whole project structure including optimizations and bug fixes
159
main.go
|
@ -2,162 +2,19 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"embed"
|
"embed"
|
||||||
_ "embed"
|
"velvettear/go-scan/src/config"
|
||||||
"encoding/json"
|
"velvettear/go-scan/src/util/scans"
|
||||||
"fmt"
|
"velvettear/go-scan/src/web"
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
"velvettear/go-scan/config"
|
|
||||||
"velvettear/go-scan/log"
|
|
||||||
"velvettear/go-scan/util/date"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed resources
|
//go:embed static
|
||||||
var resources embed.FS
|
var files embed.FS
|
||||||
|
|
||||||
var configuration config.Config
|
var configuration config.Config
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
configuration = config.New()
|
configuration = config.New()
|
||||||
startServer()
|
scans.SetScannerConfig(configuration.ScannerConfig)
|
||||||
}
|
server := web.Server(configuration.ServerConfig.Address, configuration.ServerConfig.Port, files)
|
||||||
|
server.Run()
|
||||||
func startServer() {
|
|
||||||
serverAddress := configuration.ServerConfig.Address + ":" + configuration.ServerConfig.Port
|
|
||||||
http.HandleFunc("/favicon.ico", serveResources)
|
|
||||||
http.HandleFunc("/resources/", serveResources)
|
|
||||||
http.HandleFunc("/", handleHTTPRequests)
|
|
||||||
log.Info("starting server '" + serverAddress + "'...")
|
|
||||||
error := http.ListenAndServe(serverAddress, nil)
|
|
||||||
if error != nil {
|
|
||||||
log.Fatal("an error occured starting the server", error.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func serveResources(writer http.ResponseWriter, request *http.Request) {
|
|
||||||
var resource string
|
|
||||||
if strings.HasSuffix(request.URL.Path, "favicon.ico") {
|
|
||||||
resource = "resources/gopher.png"
|
|
||||||
} else {
|
|
||||||
resource = strings.TrimPrefix(request.URL.Path, "/")
|
|
||||||
}
|
|
||||||
bytes, error := resources.ReadFile(resource)
|
|
||||||
if error != nil {
|
|
||||||
log.Error("an error occured serving the resource '"+resource+"'", error.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.Debug("serving '" + resource + "'...")
|
|
||||||
if strings.HasSuffix(resource, "svg") {
|
|
||||||
writer.Header().Set("Content-Type", "image/svg+xml")
|
|
||||||
}
|
|
||||||
writer.Write(bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleHTTPRequests(writer http.ResponseWriter, request *http.Request) {
|
|
||||||
if strings.ToLower(request.Method) == "post" {
|
|
||||||
result := handleScan(request)
|
|
||||||
writer.Header().Set("Content-Type", "application/json")
|
|
||||||
json, _ := json.Marshal(result)
|
|
||||||
writer.Write(json)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
resource := "resources/index.html"
|
|
||||||
bytes, error := resources.ReadFile(resource)
|
|
||||||
if error != nil {
|
|
||||||
log.Error("an error occured serving the resource '"+resource+"'", error.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.Debug("serving '" + resource + "'...")
|
|
||||||
writer.Write(bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleScan(request *http.Request) *result {
|
|
||||||
log.Info("starting scan...")
|
|
||||||
timestamp := date.Milliseconds()
|
|
||||||
|
|
||||||
var parameters requestParameters
|
|
||||||
parseErr := json.NewDecoder(request.Body).Decode(¶meters)
|
|
||||||
if parseErr != nil {
|
|
||||||
log.Error("error parsing request parameters", parseErr.Error())
|
|
||||||
}
|
|
||||||
scanName := generateScanName(parameters.Filename)
|
|
||||||
args := []string{}
|
|
||||||
if len(configuration.ScannerConfig.Scanner) > 0 {
|
|
||||||
args = append(args, "-d")
|
|
||||||
args = append(args, configuration.ScannerConfig.Scanner)
|
|
||||||
}
|
|
||||||
args = append(args, "-o")
|
|
||||||
args = append(args, scanName)
|
|
||||||
extraArgs := strings.Split(configuration.ScannerConfig.Arguments, " ")
|
|
||||||
for index := 0; index < len(extraArgs); index++ {
|
|
||||||
args = append(args, extraArgs[index])
|
|
||||||
}
|
|
||||||
log.Debug("executing command 'scanimage'...", args...)
|
|
||||||
scanCmd := exec.Command(
|
|
||||||
"scanimage",
|
|
||||||
args...,
|
|
||||||
)
|
|
||||||
_, err := scanCmd.Output()
|
|
||||||
if err != nil {
|
|
||||||
log.Error("an error occured executing the scan", err.Error())
|
|
||||||
result := &result{
|
|
||||||
State: "error",
|
|
||||||
Message: err.Error(),
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
result := &result{
|
|
||||||
State: "ok",
|
|
||||||
Message: scanName,
|
|
||||||
}
|
|
||||||
log.Info("finished scan after "+strconv.Itoa(date.GetTimeDifference(timestamp))+"ms", scanName)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func generateScanName(filename string) string {
|
|
||||||
if len(filename) == 0 {
|
|
||||||
day := fmt.Sprint(time.Now().Day())
|
|
||||||
if len(day) < 2 {
|
|
||||||
day = "0" + day
|
|
||||||
}
|
|
||||||
month := fmt.Sprint(int(time.Now().Month()))
|
|
||||||
if len(month) < 2 {
|
|
||||||
month = "0" + month
|
|
||||||
}
|
|
||||||
hour := fmt.Sprint(time.Now().Hour())
|
|
||||||
if len(hour) < 2 {
|
|
||||||
hour = "0" + hour
|
|
||||||
}
|
|
||||||
minute := fmt.Sprint(time.Now().Minute())
|
|
||||||
if len(minute) < 2 {
|
|
||||||
minute = "0" + minute
|
|
||||||
}
|
|
||||||
second := fmt.Sprint(time.Now().Second())
|
|
||||||
if len(second) < 2 {
|
|
||||||
second = "0" + second
|
|
||||||
}
|
|
||||||
filename = day + month + fmt.Sprint(time.Now().Year()) + "-" + hour + minute + second
|
|
||||||
}
|
|
||||||
if !strings.HasSuffix(filename, ".png") {
|
|
||||||
filename += ".png"
|
|
||||||
}
|
|
||||||
error := os.MkdirAll(configuration.ScannerConfig.OutputDirectory, 0755)
|
|
||||||
if error != nil {
|
|
||||||
log.Fatal("an error occurred creating the output directory", error.Error())
|
|
||||||
}
|
|
||||||
return configuration.ScannerConfig.OutputDirectory + filename
|
|
||||||
}
|
|
||||||
|
|
||||||
// structs
|
|
||||||
type result struct {
|
|
||||||
State string
|
|
||||||
Message string
|
|
||||||
}
|
|
||||||
|
|
||||||
type requestParameters struct {
|
|
||||||
Filename string
|
|
||||||
}
|
}
|
||||||
|
|
Before Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 713 B |
|
@ -3,17 +3,17 @@ package config
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"velvettear/go-scan/util/environment"
|
"velvettear/go-scan/src/util/environment"
|
||||||
)
|
)
|
||||||
|
|
||||||
// exported functions
|
// exported functions
|
||||||
func New() Config {
|
func New() Config {
|
||||||
config := Config{
|
config := Config{
|
||||||
ServerConfig: serverConfig{
|
ServerConfig: ServerConfig{
|
||||||
Address: environment.New("GO_SCAN_ADDRESS", "0.0.0.0").Value(),
|
Address: environment.New("GO_SCAN_ADDRESS", "0.0.0.0").Value(),
|
||||||
Port: environment.New("GO_SCAN_PORT", "9000").Value(),
|
Port: environment.New("GO_SCAN_PORT", "9000").Value(),
|
||||||
},
|
},
|
||||||
ScannerConfig: scannerConfig{
|
ScannerConfig: ScannerConfig{
|
||||||
Scanner: environment.New("GO_SCAN_SCANNER", "").Value(),
|
Scanner: environment.New("GO_SCAN_SCANNER", "").Value(),
|
||||||
OutputDirectory: environment.New("GO_SCAN_OUTPUTDIRECTORY", os.TempDir()).Value(),
|
OutputDirectory: environment.New("GO_SCAN_OUTPUTDIRECTORY", os.TempDir()).Value(),
|
||||||
Arguments: environment.New("GO_SCAN_ARGUMENTS", "").Value(),
|
Arguments: environment.New("GO_SCAN_ARGUMENTS", "").Value(),
|
||||||
|
@ -27,16 +27,16 @@ func New() Config {
|
||||||
|
|
||||||
// structs
|
// structs
|
||||||
type Config struct {
|
type Config struct {
|
||||||
ServerConfig serverConfig
|
ServerConfig ServerConfig
|
||||||
ScannerConfig scannerConfig
|
ScannerConfig ScannerConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
type serverConfig struct {
|
type ServerConfig struct {
|
||||||
Port string
|
Port string
|
||||||
Address string
|
Address string
|
||||||
}
|
}
|
||||||
|
|
||||||
type scannerConfig struct {
|
type ScannerConfig struct {
|
||||||
Scanner string
|
Scanner string
|
||||||
OutputDirectory string
|
OutputDirectory string
|
||||||
Arguments string
|
Arguments string
|
|
@ -3,7 +3,7 @@ package log
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"velvettear/go-scan/util/date"
|
"velvettear/go-scan/src/util/date"
|
||||||
)
|
)
|
||||||
|
|
||||||
// exported functions
|
// exported functions
|
|
@ -36,12 +36,13 @@ func New() Date {
|
||||||
Hour: hour,
|
Hour: hour,
|
||||||
Minute: minute,
|
Minute: minute,
|
||||||
Second: second,
|
Second: second,
|
||||||
GetFormattedDate: func() string {
|
|
||||||
return day + "." + month + "." + year + " " + hour + ":" + minute + ":" + second
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (date Date) GetFormattedDate() string {
|
||||||
|
return date.Day + "." + date.Month + "." + date.Year + " " + date.Hour + ":" + date.Minute + ":" + date.Second
|
||||||
|
}
|
||||||
|
|
||||||
func Milliseconds() int {
|
func Milliseconds() int {
|
||||||
return int(time.Now().UnixMilli())
|
return int(time.Now().UnixMilli())
|
||||||
}
|
}
|
||||||
|
@ -50,15 +51,11 @@ func GetTimeDifference(timestamp int) int {
|
||||||
return Milliseconds() - timestamp
|
return Milliseconds() - timestamp
|
||||||
}
|
}
|
||||||
|
|
||||||
// structs
|
|
||||||
type getFormattedDate func() string
|
|
||||||
|
|
||||||
type Date struct {
|
type Date struct {
|
||||||
Day string
|
Day string
|
||||||
Month string
|
Month string
|
||||||
Year string
|
Year string
|
||||||
Hour string
|
Hour string
|
||||||
Minute string
|
Minute string
|
||||||
Second string
|
Second string
|
||||||
GetFormattedDate getFormattedDate
|
|
||||||
}
|
}
|
114
src/util/scans/scans.go
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
package scans
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
"velvettear/go-scan/src/config"
|
||||||
|
"velvettear/go-scan/src/log"
|
||||||
|
"velvettear/go-scan/src/util/date"
|
||||||
|
)
|
||||||
|
|
||||||
|
var scannerConfig config.ScannerConfig
|
||||||
|
|
||||||
|
// structs
|
||||||
|
type scan struct {
|
||||||
|
FileName string
|
||||||
|
ScanName string
|
||||||
|
}
|
||||||
|
|
||||||
|
type result struct {
|
||||||
|
State string
|
||||||
|
Message string
|
||||||
|
}
|
||||||
|
|
||||||
|
// exported functions
|
||||||
|
func New(request *http.Request) scan {
|
||||||
|
var scan scan
|
||||||
|
data, _ := io.ReadAll(request.Body)
|
||||||
|
json.Unmarshal(data, &scan)
|
||||||
|
scan.generateScanName()
|
||||||
|
return scan
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetScannerConfig(config config.ScannerConfig) {
|
||||||
|
scannerConfig = config
|
||||||
|
}
|
||||||
|
|
||||||
|
func (scan scan) Execute() *result {
|
||||||
|
log.Info("starting scan...")
|
||||||
|
timestamp := date.Milliseconds()
|
||||||
|
args := []string{}
|
||||||
|
if len(scannerConfig.Scanner) > 0 {
|
||||||
|
args = append(args, "-d")
|
||||||
|
args = append(args, scannerConfig.Scanner)
|
||||||
|
}
|
||||||
|
args = append(args, "-o")
|
||||||
|
args = append(args, scan.ScanName)
|
||||||
|
extraArgs := strings.Split(scannerConfig.Arguments, " ")
|
||||||
|
for index := 0; index < len(extraArgs); index++ {
|
||||||
|
args = append(args, extraArgs[index])
|
||||||
|
}
|
||||||
|
log.Debug("executing command 'scanimage'...", args...)
|
||||||
|
scanCmd := exec.Command(
|
||||||
|
"scanimage",
|
||||||
|
args...,
|
||||||
|
)
|
||||||
|
_, err := scanCmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
log.Error("an error occured executing the scan", err.Error())
|
||||||
|
result := &result{
|
||||||
|
State: "error",
|
||||||
|
Message: err.Error(),
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
result := &result{
|
||||||
|
State: "ok",
|
||||||
|
Message: scan.ScanName,
|
||||||
|
}
|
||||||
|
log.Info("finished scan after "+strconv.Itoa(date.GetTimeDifference(timestamp))+"ms", scan.ScanName)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// unexported functions
|
||||||
|
func (scan scan) generateScanName() string {
|
||||||
|
if len(scan.FileName) == 0 {
|
||||||
|
day := fmt.Sprint(time.Now().Day())
|
||||||
|
if len(day) < 2 {
|
||||||
|
day = "0" + day
|
||||||
|
}
|
||||||
|
month := fmt.Sprint(int(time.Now().Month()))
|
||||||
|
if len(month) < 2 {
|
||||||
|
month = "0" + month
|
||||||
|
}
|
||||||
|
hour := fmt.Sprint(time.Now().Hour())
|
||||||
|
if len(hour) < 2 {
|
||||||
|
hour = "0" + hour
|
||||||
|
}
|
||||||
|
minute := fmt.Sprint(time.Now().Minute())
|
||||||
|
if len(minute) < 2 {
|
||||||
|
minute = "0" + minute
|
||||||
|
}
|
||||||
|
second := fmt.Sprint(time.Now().Second())
|
||||||
|
if len(second) < 2 {
|
||||||
|
second = "0" + second
|
||||||
|
}
|
||||||
|
scan.FileName = day + month + fmt.Sprint(time.Now().Year()) + "-" + hour + minute + second
|
||||||
|
}
|
||||||
|
if !strings.HasSuffix(scan.FileName, ".png") {
|
||||||
|
scan.FileName += ".png"
|
||||||
|
}
|
||||||
|
error := os.MkdirAll(scannerConfig.OutputDirectory, 0755)
|
||||||
|
if error != nil {
|
||||||
|
log.Fatal("an error occurred creating the output directory", error.Error())
|
||||||
|
}
|
||||||
|
scan.ScanName = scannerConfig.OutputDirectory + scan.FileName
|
||||||
|
return scan.ScanName
|
||||||
|
}
|
157
src/web/contentTypes.go
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
package web
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
func getContentType(file string) string {
|
||||||
|
parts := strings.Split(file, ".")
|
||||||
|
extension := parts[len(parts)-1]
|
||||||
|
switch extension {
|
||||||
|
case ".aac":
|
||||||
|
return "audio/aac"
|
||||||
|
case "abw":
|
||||||
|
return "application/x-abiword"
|
||||||
|
case "arc":
|
||||||
|
return "application/x-freearc"
|
||||||
|
case "avif":
|
||||||
|
return "image/avif"
|
||||||
|
case "avi":
|
||||||
|
return "video/x-msvideo"
|
||||||
|
case "azw":
|
||||||
|
return "application/vnd.amazon.ebook"
|
||||||
|
case "bin":
|
||||||
|
return "application/octet-stream"
|
||||||
|
case "bmp":
|
||||||
|
return "image/bmp"
|
||||||
|
case "bz":
|
||||||
|
return "application/x-bzip"
|
||||||
|
case "bz2":
|
||||||
|
return "application/x-bzip2"
|
||||||
|
case "cda":
|
||||||
|
return "application/x-cdf"
|
||||||
|
case "csh":
|
||||||
|
return "application/x-csh"
|
||||||
|
case "css":
|
||||||
|
return "text/css"
|
||||||
|
case "csv":
|
||||||
|
return "text/csv"
|
||||||
|
case "doc":
|
||||||
|
return "application/msword"
|
||||||
|
case "docx":
|
||||||
|
return "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
||||||
|
case "eot":
|
||||||
|
return "application/vnd.ms-fontobject"
|
||||||
|
case "epub":
|
||||||
|
return "application/epub+zip"
|
||||||
|
case "gz":
|
||||||
|
return "application/gzip"
|
||||||
|
case "gif":
|
||||||
|
return "image/gif"
|
||||||
|
case "htm":
|
||||||
|
case "html":
|
||||||
|
return "text/html"
|
||||||
|
case "ico":
|
||||||
|
return "image/vnd.microsoft.icon"
|
||||||
|
case "ics":
|
||||||
|
return "text/calendar"
|
||||||
|
case "jar":
|
||||||
|
return "application/java-archive"
|
||||||
|
case "jpeg":
|
||||||
|
case "jpg":
|
||||||
|
return "image/jpeg"
|
||||||
|
case "js":
|
||||||
|
return "text/javascript"
|
||||||
|
case "json":
|
||||||
|
return "application/json"
|
||||||
|
case "jsonld":
|
||||||
|
return "application/ld+json"
|
||||||
|
case "mid":
|
||||||
|
case "midi":
|
||||||
|
return "audio/midi audio/x-midi"
|
||||||
|
case "mjs":
|
||||||
|
return "text/javascript"
|
||||||
|
case "mp3":
|
||||||
|
return "audio/mpeg"
|
||||||
|
case "mp4":
|
||||||
|
return "video/mp4"
|
||||||
|
case "mpeg":
|
||||||
|
return "video/mpeg"
|
||||||
|
case "mpkg":
|
||||||
|
return "application/vnd.apple.installer+xml"
|
||||||
|
case "odp":
|
||||||
|
return "application/vnd.oasis.opendocument.presentation"
|
||||||
|
case "ods":
|
||||||
|
return "application/vnd.oasis.opendocument.spreadsheet"
|
||||||
|
case "odt":
|
||||||
|
return "application/vnd.oasis.opendocument.text"
|
||||||
|
case "oga":
|
||||||
|
return "audio/ogg"
|
||||||
|
case "ogv":
|
||||||
|
return "video/ogg"
|
||||||
|
case "ogx":
|
||||||
|
return "application/ogg"
|
||||||
|
case "opus":
|
||||||
|
return "audio/opus"
|
||||||
|
case "otf":
|
||||||
|
return "font/otf"
|
||||||
|
case "png":
|
||||||
|
return "image/png"
|
||||||
|
case "pdf":
|
||||||
|
return "application/pdf"
|
||||||
|
case "php":
|
||||||
|
return "application/x-httpd-php"
|
||||||
|
case "ppt":
|
||||||
|
return "application/vnd.ms-powerpoint"
|
||||||
|
case "pptx":
|
||||||
|
return "application/vnd.openxmlformats-officedocument.presentationml.presentation"
|
||||||
|
case "rar":
|
||||||
|
return "application/vnd.rar"
|
||||||
|
case "rtf":
|
||||||
|
return "application/rtf"
|
||||||
|
case "sh":
|
||||||
|
return "application/x-sh"
|
||||||
|
case "svg":
|
||||||
|
return "image/svg+xml"
|
||||||
|
case "swf":
|
||||||
|
return "application/x-shockwave-flash"
|
||||||
|
case "tar":
|
||||||
|
return "application/x-tar"
|
||||||
|
case "tif":
|
||||||
|
case "tiff":
|
||||||
|
return "image/tiff"
|
||||||
|
case "ts":
|
||||||
|
return "video/mp2t"
|
||||||
|
case "ttf":
|
||||||
|
return "font/ttf"
|
||||||
|
case "txt":
|
||||||
|
return "text/plain"
|
||||||
|
case "vsd":
|
||||||
|
return "application/vnd.visio"
|
||||||
|
case "wav":
|
||||||
|
return "audio/wav"
|
||||||
|
case "weba":
|
||||||
|
return "audio/webm"
|
||||||
|
case "webm":
|
||||||
|
return "video/webm"
|
||||||
|
case "webp":
|
||||||
|
return "image/webp"
|
||||||
|
case "woff":
|
||||||
|
return "font/woff"
|
||||||
|
case "woff2":
|
||||||
|
return "font/woff2"
|
||||||
|
case "xhtml":
|
||||||
|
return "application/xhtml+xml"
|
||||||
|
case "xls":
|
||||||
|
return "application/vnd.ms-excel"
|
||||||
|
case "xlsx":
|
||||||
|
return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
||||||
|
case "xml":
|
||||||
|
return "application/xml"
|
||||||
|
case "xul":
|
||||||
|
return "application/vnd.mozilla.xul+xml"
|
||||||
|
case "zip":
|
||||||
|
return "application/zip"
|
||||||
|
case "7z":
|
||||||
|
return "application/x-7z-compressed"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
15
src/web/requestParameters.go
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
package web
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"velvettear/go-scan/src/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// exported functions
|
||||||
|
func ParseRequestParameters(request *http.Request, parameters struct{}) {
|
||||||
|
parseErr := json.NewDecoder(request.Body).Decode(¶meters)
|
||||||
|
if parseErr != nil {
|
||||||
|
log.Error("error parsing request parameters", parseErr.Error())
|
||||||
|
}
|
||||||
|
}
|
77
src/web/server.go
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
package web
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"velvettear/go-scan/src/log"
|
||||||
|
"velvettear/go-scan/src/util/scans"
|
||||||
|
)
|
||||||
|
|
||||||
|
// struct
|
||||||
|
type server struct {
|
||||||
|
address string
|
||||||
|
port string
|
||||||
|
files embed.FS
|
||||||
|
}
|
||||||
|
|
||||||
|
// "constructor"
|
||||||
|
func Server(address string, port string, files embed.FS) server {
|
||||||
|
server := server{
|
||||||
|
address: address,
|
||||||
|
port: port,
|
||||||
|
files: files,
|
||||||
|
}
|
||||||
|
return server
|
||||||
|
}
|
||||||
|
|
||||||
|
// exported functions
|
||||||
|
func (server server) Run() {
|
||||||
|
if len(server.address) == 0 || len(server.port) == 0 {
|
||||||
|
log.Fatal("could not start the server, address or port is not set")
|
||||||
|
}
|
||||||
|
serverAddress := server.address + ":" + server.port
|
||||||
|
http.HandleFunc("/", server.handleRequest)
|
||||||
|
log.Info("starting server '" + serverAddress + "'...")
|
||||||
|
err := http.ListenAndServe(serverAddress, nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("an error occured starting the server", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// unexported functions
|
||||||
|
func (server server) handleRequest(writer http.ResponseWriter, request *http.Request) {
|
||||||
|
if strings.ToLower(request.Method) == "post" {
|
||||||
|
server.handlePost(writer, request)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
requestedFile := strings.TrimPrefix(request.URL.Path, "/")
|
||||||
|
switch requestedFile {
|
||||||
|
case "favicon.ico":
|
||||||
|
requestedFile = "img/" + requestedFile
|
||||||
|
case "":
|
||||||
|
requestedFile = "html/index.html"
|
||||||
|
}
|
||||||
|
requestedFile = "static/" + requestedFile
|
||||||
|
bytes, err := server.files.ReadFile(requestedFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("an error occured serving the static file '"+requestedFile+"'", err.Error())
|
||||||
|
writer.WriteHeader(404)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
contentType := getContentType(requestedFile)
|
||||||
|
if len(contentType) > 0 {
|
||||||
|
writer.Header().Set("Content-Type", contentType)
|
||||||
|
}
|
||||||
|
log.Debug("serving file '" + requestedFile + "'...")
|
||||||
|
writer.Write(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server server) handlePost(writer http.ResponseWriter, request *http.Request) {
|
||||||
|
scan := scans.New(request)
|
||||||
|
result := scan.Execute()
|
||||||
|
writer.Header().Set("Content-Type", "application/json")
|
||||||
|
json, _ := json.Marshal(result)
|
||||||
|
writer.Write(json)
|
||||||
|
}
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>go-scan</title>
|
<title>go-scan</title>
|
||||||
<link href="/resources/firacode.ttf" rel="stylesheet">
|
<link href="/fonts/firacode.ttf" rel="stylesheet">
|
||||||
<link href="/resources/styles.css" rel="stylesheet">
|
<link href="/css/styles.css" rel="stylesheet">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
<h1>go-scan</h1>
|
<h1>go-scan</h1>
|
||||||
</div>
|
</div>
|
||||||
<div id="button" onclick="startScan()">
|
<div id="button" onclick="startScan()">
|
||||||
<img id="button-img" src="/resources/icon.png">
|
<img id="button-img" src="/img/icon.png">
|
||||||
</div>
|
</div>
|
||||||
<div id="input">
|
<div id="input">
|
||||||
<input id="input-filename" type="text" placeholder="filename...">
|
<input id="input-filename" type="text" placeholder="filename...">
|
||||||
|
@ -24,11 +24,11 @@
|
||||||
<a href="https://velvettear.de" target="_blank">
|
<a href="https://velvettear.de" target="_blank">
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
<span>made with</span>
|
<span>made with</span>
|
||||||
<img id="heart-img" src="/resources/hearts-fill.svg">
|
<img id="heart-img" src="/img/hearts-fill.svg">
|
||||||
<span>by velvettear</span>
|
<span>by velvettear</span>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<script src="/resources/main.js"></script>
|
<script src="/js/main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
BIN
static/img/favicon.ico
Normal file
After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 603 B After Width: | Height: | Size: 603 B |
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.7 KiB |