mirror of
https://github.com/wailsapp/wails.git
synced 2026-03-14 22:55:48 +01:00
[v2] Consolidate processRequest, improve logging and error handling (#1158)
This commit is contained in:
parent
944494c4ef
commit
c63b1f1981
5 changed files with 114 additions and 103 deletions
55
v2/internal/frontend/desktop/common/process_request.go
Normal file
55
v2/internal/frontend/desktop/common/process_request.go
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/assetserver"
|
||||
)
|
||||
|
||||
type RequestRespone struct {
|
||||
Body []byte
|
||||
MimeType string
|
||||
StatusCode int
|
||||
}
|
||||
|
||||
func (r RequestRespone) StatusText() string {
|
||||
return http.StatusText(r.StatusCode)
|
||||
}
|
||||
|
||||
func (r RequestRespone) String() string {
|
||||
return fmt.Sprintf("Body: '%s', StatusCode: %d", string(r.Body), r.StatusCode)
|
||||
}
|
||||
|
||||
func ProcessRequest(uri string, assets *assetserver.DesktopAssetServer, expectedScheme string, expectedHosts ...string) (RequestRespone, error) {
|
||||
// Translate URI to file
|
||||
file, err := translateUriToFile(uri, expectedScheme, expectedHosts...)
|
||||
if err != nil {
|
||||
if err == ErrUnexpectedHost {
|
||||
body := fmt.Sprintf("expected host one of \"%s\"", strings.Join(expectedHosts, ","))
|
||||
return textResponse(body, http.StatusInternalServerError), err
|
||||
}
|
||||
|
||||
return RequestRespone{StatusCode: http.StatusInternalServerError}, err
|
||||
}
|
||||
|
||||
content, mimeType, err := assets.Load(file)
|
||||
if err != nil {
|
||||
statusCode := http.StatusInternalServerError
|
||||
if os.IsNotExist(err) {
|
||||
statusCode = http.StatusNotFound
|
||||
}
|
||||
return RequestRespone{StatusCode: statusCode}, err
|
||||
}
|
||||
|
||||
return RequestRespone{Body: content, MimeType: mimeType, StatusCode: http.StatusOK}, nil
|
||||
}
|
||||
|
||||
func textResponse(body string, statusCode int) RequestRespone {
|
||||
if body == "" {
|
||||
return RequestRespone{StatusCode: statusCode}
|
||||
}
|
||||
return RequestRespone{Body: []byte(body), MimeType: "text/plain;charset=UTF-8", StatusCode: statusCode}
|
||||
}
|
||||
|
|
@ -1,20 +1,34 @@
|
|||
package common
|
||||
|
||||
import "net/url"
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
func TranslateUriToFile(uri string, expectedScheme string, expectedHost string) (file string, match bool, err error) {
|
||||
var ErrUnexpectedScheme = fmt.Errorf("unexpected scheme")
|
||||
var ErrUnexpectedHost = fmt.Errorf("unexpected host")
|
||||
|
||||
func translateUriToFile(uri string, expectedScheme string, expectedHosts ...string) (file string, err error) {
|
||||
url, err := url.Parse(uri)
|
||||
if err != nil {
|
||||
return "", false, err
|
||||
return "", err
|
||||
}
|
||||
|
||||
if url.Scheme != expectedScheme || url.Host != expectedHost {
|
||||
return "", false, nil
|
||||
if url.Scheme != expectedScheme {
|
||||
return "", ErrUnexpectedScheme
|
||||
}
|
||||
|
||||
filePath := url.Path
|
||||
if filePath == "" {
|
||||
filePath = "/"
|
||||
for _, expectedHost := range expectedHosts {
|
||||
if url.Host != expectedHost {
|
||||
continue
|
||||
}
|
||||
|
||||
filePath := url.Path
|
||||
if filePath == "" {
|
||||
filePath = "/"
|
||||
}
|
||||
return filePath, nil
|
||||
}
|
||||
return filePath, true, nil
|
||||
|
||||
return "", ErrUnexpectedHost
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,10 +16,8 @@ import "C"
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"unsafe"
|
||||
|
||||
|
|
@ -280,40 +278,21 @@ func (f *Frontend) ExecJS(js string) {
|
|||
func (f *Frontend) processRequest(r *request) {
|
||||
uri := C.GoString(r.url)
|
||||
|
||||
var _contents []byte
|
||||
var _mimetype string
|
||||
|
||||
// Translate URI to file
|
||||
file, match, err := common.TranslateUriToFile(uri, "wails", "wails")
|
||||
if err == nil {
|
||||
if !match {
|
||||
// This should never happen on darwin, because we get only called for wails://
|
||||
panic("Unexpected host for request on wails:// scheme")
|
||||
}
|
||||
|
||||
// Load file from asset store
|
||||
_contents, _mimetype, err = f.assets.Load(file)
|
||||
}
|
||||
|
||||
statusCode := 200
|
||||
res, err := common.ProcessRequest(uri, f.assets, "wails", "wails")
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
statusCode = 404
|
||||
} else {
|
||||
err = fmt.Errorf("Error processing request %s: %w", uri, err)
|
||||
f.logger.Error(err.Error())
|
||||
statusCode = 500
|
||||
}
|
||||
f.logger.Error("Error processing request '%s': %s (HttpResponse=%s)", uri, err, res)
|
||||
}
|
||||
|
||||
var data unsafe.Pointer
|
||||
if _contents != nil {
|
||||
data = unsafe.Pointer(&_contents[0])
|
||||
var content unsafe.Pointer
|
||||
var contentLen int
|
||||
if _contents := res.Body; _contents != nil {
|
||||
content = unsafe.Pointer(&_contents[0])
|
||||
contentLen = len(_contents)
|
||||
}
|
||||
mimetype := C.CString(_mimetype)
|
||||
mimetype := C.CString(res.MimeType)
|
||||
defer C.free(unsafe.Pointer(mimetype))
|
||||
|
||||
C.ProcessURLResponse(r.ctx, r.url, C.int(statusCode), mimetype, data, C.int(len(_contents)))
|
||||
C.ProcessURLResponse(r.ctx, r.url, C.int(res.StatusCode), mimetype, content, C.int(contentLen))
|
||||
}
|
||||
|
||||
//func (f *Frontend) processSystemEvent(message string) {
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ import "C"
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"text/template"
|
||||
|
|
@ -292,46 +292,23 @@ func (f *Frontend) processRequest(request unsafe.Pointer) {
|
|||
uri := C.webkit_uri_scheme_request_get_uri(req)
|
||||
goURI := C.GoString(uri)
|
||||
|
||||
file, match, err := common.TranslateUriToFile(goURI, "wails", "")
|
||||
res, err := common.ProcessRequest(goURI, f.assets, "wails", "", "null")
|
||||
if err != nil {
|
||||
// TODO Handle errors
|
||||
return
|
||||
} else if !match {
|
||||
file, match, err = common.TranslateUriToFile(goURI, "wails", "null")
|
||||
if err != nil {
|
||||
// TODO Handle errors
|
||||
return
|
||||
} else if !match {
|
||||
// This should never happen on linux, because we get only called for wails://
|
||||
panic("Unexpected host for request on wails:// scheme")
|
||||
}
|
||||
f.logger.Error("Error processing request '%s': %s (HttpResponse=%s)", goURI, err, res)
|
||||
}
|
||||
|
||||
// Load file from asset store
|
||||
content, mimeType, err := f.assets.Load(file)
|
||||
|
||||
// TODO How to return 404/500 errors to webkit?
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
message := C.CString("File not found")
|
||||
gerr := C.g_error_new_literal(C.g_quark_from_string(message), C.int(404), message)
|
||||
C.webkit_uri_scheme_request_finish_error(req, gerr)
|
||||
C.g_error_free(gerr)
|
||||
C.free(unsafe.Pointer(message))
|
||||
} else {
|
||||
err = fmt.Errorf("Error processing request %s: %v", uri, err)
|
||||
message := C.CString("Internal Error")
|
||||
gerr := C.g_error_new_literal(C.g_quark_from_string(message), C.int(500), message)
|
||||
C.webkit_uri_scheme_request_finish_error(req, gerr)
|
||||
C.g_error_free(gerr)
|
||||
C.free(unsafe.Pointer(message))
|
||||
}
|
||||
if code := res.StatusCode; code != http.StatusOK {
|
||||
message := C.CString(res.StatusText())
|
||||
gerr := C.g_error_new_literal(C.g_quark_from_string(message), C.int(code), message)
|
||||
C.webkit_uri_scheme_request_finish_error(req, gerr)
|
||||
C.g_error_free(gerr)
|
||||
C.free(unsafe.Pointer(message))
|
||||
return
|
||||
}
|
||||
|
||||
cContent := C.CString(string(content))
|
||||
cContent := C.CString(string(res.Body))
|
||||
defer C.free(unsafe.Pointer(cContent))
|
||||
cMimeType := C.CString(mimeType)
|
||||
cMimeType := C.CString(res.MimeType)
|
||||
defer C.free(unsafe.Pointer(cMimeType))
|
||||
cLen := C.long(C.strlen(cContent))
|
||||
stream := C.g_memory_input_stream_new_from_data(
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
|
@ -353,46 +352,32 @@ func (f *Frontend) processRequest(req *edge.ICoreWebView2WebResourceRequest, arg
|
|||
//Get the request
|
||||
uri, _ := req.GetUri()
|
||||
|
||||
var content []byte
|
||||
var mimeType string
|
||||
|
||||
// Translate URI to file
|
||||
file, match, err := common.TranslateUriToFile(uri, "file", "wails")
|
||||
if err == nil {
|
||||
if !match {
|
||||
// In this case we should let the WebView2 handle the request with it's default handler
|
||||
return
|
||||
}
|
||||
|
||||
// Load file from asset store
|
||||
content, mimeType, err = f.assets.Load(file)
|
||||
}
|
||||
|
||||
statusCode := 200
|
||||
reasonPhrase := "OK"
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
statusCode = 404
|
||||
reasonPhrase = "Not Found"
|
||||
} else {
|
||||
err = fmt.Errorf("Error processing request %s: %w", uri, err)
|
||||
f.logger.Error(err.Error())
|
||||
statusCode = 500
|
||||
reasonPhrase = "Internal Server Error"
|
||||
}
|
||||
res, err := common.ProcessRequest(uri, f.assets, "file", "wails")
|
||||
if err == common.ErrUnexpectedScheme {
|
||||
// In this case we should let the WebView2 handle the request with its default handler
|
||||
return
|
||||
} else if err == common.ErrUnexpectedHost {
|
||||
// This means file:// to something other than wails, should we prevent this?
|
||||
// Maybe we should introduce an AllowList for explicitly allowing schemes and hosts, this could also be interesting
|
||||
// for all other platforms to improve security.
|
||||
return // Let WebView2 handle the request with its default handler
|
||||
} else if err != nil {
|
||||
f.logger.Error("Error processing request '%s': %s (HttpResponse=%s)", uri, err, res)
|
||||
}
|
||||
|
||||
headers := []string{}
|
||||
if mimeType != "" {
|
||||
if mimeType := res.MimeType; mimeType != "" {
|
||||
headers = append(headers, "Content-Type: "+mimeType)
|
||||
}
|
||||
content := res.Body
|
||||
if content != nil && f.servingFromDisk {
|
||||
headers = append(headers, "Pragma: no-cache")
|
||||
}
|
||||
|
||||
env := f.chromium.Environment()
|
||||
response, err := env.CreateWebResourceResponse(content, statusCode, reasonPhrase, strings.Join(headers, "\n"))
|
||||
response, err := env.CreateWebResourceResponse(content, res.StatusCode, res.StatusText(), strings.Join(headers, "\n"))
|
||||
if err != nil {
|
||||
f.logger.Error("CreateWebResourceResponse Error: %s", err)
|
||||
return
|
||||
}
|
||||
defer response.Release()
|
||||
|
|
@ -400,6 +385,7 @@ func (f *Frontend) processRequest(req *edge.ICoreWebView2WebResourceRequest, arg
|
|||
// Send response back
|
||||
err = args.PutResponse(response)
|
||||
if err != nil {
|
||||
f.logger.Error("PutResponse Error: %s", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue