5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-03 01:30:32 +08:00

[v2] Improve processRequest: Handle errors and behave more like a webserver

This also fixes that requests remain in "pending" state on
darwin if e.g. a file is not found or an error occurs during
loading of the file.
This commit is contained in:
stffabi 2021-12-03 16:40:42 +01:00
parent 59d29dc12f
commit d827aafe89
7 changed files with 69 additions and 32 deletions

View File

@ -41,7 +41,7 @@ void Quit(void*);
const char* GetSize(void *ctx); const char* GetSize(void *ctx);
const char* GetPos(void *ctx); const char* GetPos(void *ctx);
void ProcessURLResponse(void *inctx, const char *url, const char *contentType, void* data, int datalength); void ProcessURLResponse(void *inctx, const char *url, int statusCode, const char *contentType, void* data, int datalength);
/* Dialogs */ /* Dialogs */

View File

@ -51,13 +51,13 @@ WailsContext* Create(const char* title, int width, int height, int frameless, in
return result; return result;
} }
void ProcessURLResponse(void *inctx, const char *url, const char *contentType, void* data, int datalength) { void ProcessURLResponse(void *inctx, const char *url, int statusCode, const char *contentType, void* data, int datalength) {
WailsContext *ctx = (__bridge WailsContext*) inctx; WailsContext *ctx = (__bridge WailsContext*) inctx;
NSString *nsurl = safeInit(url); NSString *nsurl = safeInit(url);
NSString *nsContentType = safeInit(contentType); NSString *nsContentType = safeInit(contentType);
NSData *nsdata = [NSData dataWithBytes:data length:datalength]; NSData *nsdata = [NSData dataWithBytes:data length:datalength];
[ctx processURLResponse:nsurl :nsContentType :nsdata]; [ctx processURLResponse:nsurl :statusCode :nsContentType :nsdata];
[nsdata release]; [nsdata release];
} }

View File

@ -79,7 +79,7 @@
- (void) SaveFileDialog :(NSString*)title :(NSString*)defaultFilename :(NSString*)defaultDirectory :(bool)canCreateDirectories :(bool)treatPackagesAsDirectories :(bool)showHiddenFiles :(NSString*)filters; - (void) SaveFileDialog :(NSString*)title :(NSString*)defaultFilename :(NSString*)defaultDirectory :(bool)canCreateDirectories :(bool)treatPackagesAsDirectories :(bool)showHiddenFiles :(NSString*)filters;
- (void) loadRequest:(NSString*)url; - (void) loadRequest:(NSString*)url;
- (void) processURLResponse:(NSString *)url :(NSString *)contentType :(NSData*)data; - (void) processURLResponse:(NSString *)url :(int)statusCode :(NSString *)contentType :(NSData*)data;
- (void) ExecJS:(NSString*)script; - (void) ExecJS:(NSString*)script;
- (NSScreen*) getCurrentScreen; - (NSScreen*) getCurrentScreen;

View File

@ -376,12 +376,14 @@
[self.webview evaluateJavaScript:script completionHandler:nil]; [self.webview evaluateJavaScript:script completionHandler:nil];
} }
- (void) processURLResponse:(NSString *)url :(NSString *)contentType :(NSData *)data { - (void) processURLResponse:(NSString *)url :(int)statusCode :(NSString *)contentType :(NSData *)data {
id<WKURLSchemeTask> urlSchemeTask = self.urlRequests[url]; id<WKURLSchemeTask> urlSchemeTask = self.urlRequests[url];
NSURL *nsurl = [NSURL URLWithString:url]; NSURL *nsurl = [NSURL URLWithString:url];
NSMutableDictionary *headerFields = [NSMutableDictionary new]; NSMutableDictionary *headerFields = [NSMutableDictionary new];
headerFields[@"content-type"] = contentType; if ( ![contentType isEqualToString:@""] ) {
NSHTTPURLResponse *response = [[NSHTTPURLResponse new] initWithURL:nsurl statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:headerFields]; headerFields[@"content-type"] = contentType;
}
NSHTTPURLResponse *response = [[NSHTTPURLResponse new] initWithURL:nsurl statusCode:statusCode HTTPVersion:@"HTTP/1.1" headerFields:headerFields];
[urlSchemeTask didReceiveResponse:response]; [urlSchemeTask didReceiveResponse:response];
[urlSchemeTask didReceiveData:data]; [urlSchemeTask didReceiveData:data];
[urlSchemeTask didFinish]; [urlSchemeTask didFinish];

View File

@ -16,8 +16,10 @@ import "C"
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"fmt"
"html/template" "html/template"
"log" "log"
"os"
"strconv" "strconv"
"unsafe" "unsafe"
@ -272,21 +274,32 @@ func (f *Frontend) ExecJS(js string) {
func (f *Frontend) processRequest(r *request) { func (f *Frontend) processRequest(r *request) {
uri := C.GoString(r.url) uri := C.GoString(r.url)
var _contents []byte
var _mimetype string
// Translate URI to file // Translate URI to file
file, match, err := common.TranslateUriToFile(uri, "wails", "wails") file, match, err := common.TranslateUriToFile(uri, "wails", "wails")
if err != nil { if err == nil {
// TODO Handle errors if !match {
return // This should never happen on darwin, because we get only called for wails://
} else if !match { panic("Unexpected host for request on wails:// scheme")
return }
// Load file from asset store
_contents, _mimetype, err = f.assets.Load(file)
} }
_contents, _mimetype, err := f.assets.Load(file) statusCode := 200
if err != nil { if err != nil {
f.logger.Error(err.Error()) if os.IsNotExist(err) {
//TODO: Handle errors statusCode = 404
return } else {
err = fmt.Errorf("Error processing request %s: %w", uri, err)
f.logger.Error(err.Error())
statusCode = 500
}
} }
var data unsafe.Pointer var data unsafe.Pointer
if _contents != nil { if _contents != nil {
data = unsafe.Pointer(&_contents[0]) data = unsafe.Pointer(&_contents[0])
@ -294,7 +307,7 @@ func (f *Frontend) processRequest(r *request) {
mimetype := C.CString(_mimetype) mimetype := C.CString(_mimetype)
defer C.free(unsafe.Pointer(mimetype)) defer C.free(unsafe.Pointer(mimetype))
C.ProcessURLResponse(r.ctx, r.url, mimetype, data, C.int(len(_contents))) C.ProcessURLResponse(r.ctx, r.url, C.int(statusCode), mimetype, data, C.int(len(_contents)))
} }
//func (f *Frontend) processSystemEvent(message string) { //func (f *Frontend) processSystemEvent(message string) {

View File

@ -333,7 +333,8 @@ func (f *Frontend) processRequest(request unsafe.Pointer) {
// TODO Handle errors // TODO Handle errors
return return
} else if !match { } else if !match {
return // This should never happen on linux, because we get only called for wails://
panic("Unexpected host for request on wails:// scheme")
} }
// Load file from asset store // Load file from asset store
@ -342,6 +343,8 @@ func (f *Frontend) processRequest(request unsafe.Pointer) {
return return
} }
// TODO How to return 404/500 errors to webkit?
cContent := C.CString(string(content)) cContent := C.CString(string(content))
defer C.free(unsafe.Pointer(cContent)) defer C.free(unsafe.Pointer(cContent))
cMimeType := C.CString(mimeType) cMimeType := C.CString(mimeType)

View File

@ -8,6 +8,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"log" "log"
"os"
"runtime" "runtime"
"strconv" "strconv"
"strings" "strings"
@ -336,26 +337,45 @@ func (f *Frontend) processRequest(req *edge.ICoreWebView2WebResourceRequest, arg
//Get the request //Get the request
uri, _ := req.GetUri() uri, _ := req.GetUri()
var content []byte
var mimeType string
// Translate URI to file
file, match, err := common.TranslateUriToFile(uri, "file", "wails") file, match, err := common.TranslateUriToFile(uri, "file", "wails")
if err != nil { if err == nil {
// TODO Handle errors if !match {
return // In this case we should let the WebView2 handle the request with it's default handler
} else if !match { return
return }
// Load file from asset store
content, mimeType, err = f.assets.Load(file)
} }
// Load file from asset store statusCode := 200
content, mimeType, err := f.assets.Load(file) reasonPhrase := "OK"
if err != nil { if err != nil {
return 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"
}
}
headers := []string{}
if mimeType != "" {
headers = append(headers, "Content-Type: "+mimeType)
}
if content != nil && f.servingFromDisk {
headers = append(headers, "Pragma: no-cache")
} }
env := f.chromium.Environment() env := f.chromium.Environment()
headers := "Content-Type: " + mimeType response, err := env.CreateWebResourceResponse(content, statusCode, reasonPhrase, strings.Join(headers, "\n"))
if f.servingFromDisk {
headers += "\nPragma: no-cache"
}
response, err := env.CreateWebResourceResponse(content, 200, "OK", headers)
if err != nil { if err != nil {
return return
} }
@ -366,7 +386,6 @@ func (f *Frontend) processRequest(req *edge.ICoreWebView2WebResourceRequest, arg
if err != nil { if err != nil {
return return
} }
return
} }
var edgeMap = map[string]uintptr{ var edgeMap = map[string]uintptr{