Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switching between "hash" and "path" routing URL strategy #110

Merged
merged 4 commits into from
Jul 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions client/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:redux/redux.dart';
import 'package:url_strategy/url_strategy.dart';

import '../utils/platform_utils_non_web.dart'
if (dart.library.js) "../utils/platform_utils_web.dart";
import '../utils/session_store_non_web.dart'
if (dart.library.js) "../utils/session_store_web.dart";
import 'controls/create_control.dart';
import 'models/app_state.dart';
import 'models/page_view_model.dart';
import 'reducers.dart';
import 'session_store/session_store.dart'
if (dart.library.io) "session_store/session_store_io.dart"
if (dart.library.js) "session_store/session_store_js.dart";
import 'web_socket_client.dart';

const bool isProduction = bool.fromEnvironment('dart.vm.product');
Expand All @@ -35,6 +37,11 @@ void main([List<String>? args]) async {

if (kIsWeb) {
debugPrint("Flet View is running in Web mode");
var routeUrlStrategy = getRouteUrlStrategy();
debugPrint("URL Strategy: $routeUrlStrategy");
if (routeUrlStrategy == "path") {
setPathUrlStrategy();
}
} else if ((Platform.isWindows || Platform.isMacOS || Platform.isLinux) &&
!kDebugMode) {
debugPrint("Flet View is running in Desktop mode");
Expand Down
10 changes: 4 additions & 6 deletions client/lib/reducers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,13 @@ import 'package:flet_view/protocol/update_control_props_payload.dart';
import 'package:flet_view/web_socket_client.dart';
import 'package:flutter/cupertino.dart';

import '../utils/platform_utils.dart'
if (dart.library.io) "../utils/platform_utils_io.dart"
if (dart.library.js) "../utils/platform_utils_js.dart";
import '../utils/platform_utils_non_web.dart'
if (dart.library.js) "../utils/platform_utils_web.dart";
import '../utils/session_store_non_web.dart'
if (dart.library.js) "../utils/session_store_web.dart";
import 'actions.dart';
import 'models/app_state.dart';
import 'models/control.dart';
import 'session_store/session_store.dart'
if (dart.library.io) "session_store/session_store_io.dart"
if (dart.library.js) "session_store/session_store_js.dart";
import 'utils/desktop.dart';
import 'utils/uri.dart';

Expand Down
9 changes: 0 additions & 9 deletions client/lib/session_store/session_store.dart

This file was deleted.

3 changes: 0 additions & 3 deletions client/lib/utils/platform_utils.dart

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
bool isProgressiveWebApp() {
return false;
}

String getRouteUrlStrategy() {
return "";
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,9 @@ bool isProgressiveWebApp() {
window.matchMedia('(display-mode: fullscreen)').matches ||
window.matchMedia('(display-mode: minimal-ui)').matches;
}

String getRouteUrlStrategy() {
var meta =
document.head?.querySelector("meta[name='flet-route-url-strategy']");
return meta != null ? meta.attributes["content"]! : "";
}
9 changes: 8 additions & 1 deletion client/lib/utils/uri.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import 'strings.dart';

String getWebPageName(Uri uri) {
return trim(uri.path, "/");
var urlPath = trim(uri.path, "/");
if (urlPath != "") {
var pathParts = urlPath.split("/");
if (pathParts.length > 1) {
urlPath = pathParts.sublist(0, 2).join("/");
}
}
return urlPath;
}

String getWebSocketEndpoint(Uri uri) {
Expand Down
19 changes: 19 additions & 0 deletions client/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_web_plugins:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
http:
dependency: "direct main"
description:
Expand All @@ -137,6 +142,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "3.2.0"
js:
dependency: transitive
description:
name: js
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.4"
lints:
dependency: transitive
description:
Expand Down Expand Up @@ -247,6 +259,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
url_strategy:
dependency: "direct main"
description:
name: url_strategy
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.0"
vector_math:
dependency: transitive
description:
Expand Down
1 change: 1 addition & 0 deletions client/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ dependencies:
window_manager: ^0.2.5
http: ^0.13.3
collection: ^1.16.0
url_strategy: ^0.2.0

dev_dependencies:
flutter_test:
Expand Down
7 changes: 7 additions & 0 deletions client/test/utils/uri_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ void main() {
expect(
getWebPageName(Uri.parse('http://localhost:8550/p/test/')), "p/test");
expect(getWebPageName(Uri.parse('http://localhost:8550/p/test')), "p/test");
expect(getWebPageName(Uri.parse('http://localhost:8550/aaa')), "aaa");
expect(getWebPageName(Uri.parse('http://localhost:8550/p/test/store')),
"p/test");
expect(
getWebPageName(
Uri.parse('http://localhost:8550/p/test/store/products/1')),
"p/test");
expect(getWebPageName(Uri.parse('http://localhost:8550/')), "");
expect(getWebPageName(Uri.parse('http://localhost:8550/#/')), "");
});
Expand Down
3 changes: 3 additions & 0 deletions client/web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
<!-- Favicon -->
<link rel="icon" type="image/png" href="favicon.png"/>

<!-- Flet specific -->
<meta name="flet-route-url-strategy" content="%FLET_ROUTE_URL_STRATEGY%">

<title>Flet</title>
<link rel="manifest" href="manifest.json">

Expand Down
15 changes: 13 additions & 2 deletions sdk/python/flet/flet.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def page(
view: AppViewer = WEB_BROWSER,
assets_dir=None,
web_renderer="canvaskit",
route_url_strategy="hash",
):
conn = _connect_internal(
page_name=name,
Expand All @@ -52,6 +53,7 @@ def page(
permissions=permissions,
assets_dir=assets_dir,
web_renderer=web_renderer,
route_url_strategy=route_url_strategy,
)
print("Page URL:", conn.page_url)
page = Page(conn, constants.ZERO_SESSION)
Expand All @@ -71,6 +73,7 @@ def app(
view: AppViewer = FLET_APP,
assets_dir=None,
web_renderer="canvaskit",
route_url_strategy="hash",
):

if target == None:
Expand All @@ -84,6 +87,7 @@ def app(
session_handler=target,
assets_dir=assets_dir,
web_renderer=web_renderer,
route_url_strategy=route_url_strategy,
)
print("App URL:", conn.page_url)

Expand Down Expand Up @@ -139,6 +143,7 @@ def _connect_internal(
session_handler=None,
assets_dir=None,
web_renderer=None,
route_url_strategy=None,
):
if share and server == None:
server = constants.HOSTED_SERVICE_URL
Expand All @@ -151,7 +156,9 @@ def _connect_internal(
# page with a custom port starts detached process
attached = False if not is_app and port != 0 else True

port = _start_flet_server(port, attached, assets_dir, web_renderer)
port = _start_flet_server(
port, attached, assets_dir, web_renderer, route_url_strategy
)
server = f"http://127.0.0.1:{port}"

connected = threading.Event()
Expand Down Expand Up @@ -219,7 +226,7 @@ def _on_ws_failed_connect():
return conn


def _start_flet_server(port, attached, assets_dir, web_renderer):
def _start_flet_server(port, attached, assets_dir, web_renderer, route_url_strategy):

if port == 0:
port = _get_free_tcp_port()
Expand Down Expand Up @@ -263,6 +270,10 @@ def _start_flet_server(port, attached, assets_dir, web_renderer):
logging.info(f"Web renderer configured: {web_renderer}")
fletd_env["FLET_WEB_RENDERER"] = web_renderer

if route_url_strategy != None:
logging.info(f"Route URL strategy configured: {route_url_strategy}")
fletd_env["FLET_ROUTE_URL_STRATEGY"] = route_url_strategy

args = [fletd_path, "--port", str(port)]

creationflags = 0
Expand Down
13 changes: 11 additions & 2 deletions server/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,10 @@ const (
defaultMasterSecretKey = "master_secret_key"

// development
staticRootDir = "STATIC_ROOT_DIR"
webRenderer = "WEB_RENDERER"
staticRootDir = "STATIC_ROOT_DIR"
webRenderer = "WEB_RENDERER"
routeUrlStrategy = "ROUTE_URL_STRATEGY"
defaultRouteUrlStrategy = "hash"
)

func init() {
Expand Down Expand Up @@ -124,6 +126,9 @@ func init() {
// security
viper.SetDefault(cookieSecret, getSecretManagerValue(cookieSecret, defaultCookieSecret))
viper.SetDefault(masterSecretKey, getSecretManagerValue(masterSecretKey, defaultMasterSecretKey))

// development
viper.SetDefault(routeUrlStrategy, defaultRouteUrlStrategy)
}

func getSecretManagerValue(name string, defaultValue string) string {
Expand Down Expand Up @@ -288,3 +293,7 @@ func StaticRootDir() string {
func WebRenderer() string {
return viper.GetString(webRenderer)
}

func RouteUrlStrategy() string {
return viper.GetString(routeUrlStrategy)
}
6 changes: 6 additions & 0 deletions server/model/page_name.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const (
type PageName struct {
Account string
Name string
IsIndex bool
}

func ParsePageName(pageName string) (*PageName, error) {
Expand All @@ -27,6 +28,7 @@ func ParsePageName(pageName string) (*PageName, error) {
return &PageName{
Account: publicAccount,
Name: indexPage,
IsIndex: true,
}, nil
}

Expand Down Expand Up @@ -62,6 +64,10 @@ func ParsePageName(pageName string) (*PageName, error) {
return nil, fmt.Errorf("page name exceeds the maximum allowed size of %d symbols", maxSlugSize)
}

if p.Account == publicAccount && p.Name == indexPage {
p.IsIndex = true
}

return p, nil
}

Expand Down
11 changes: 8 additions & 3 deletions server/page/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,14 @@ func (c *Client) registerWebClientCore(request *RegisterWebClientRequestPayload)

// get page
page := store.GetPageByName(pageName.String())
if page == nil {
response.Error = pageNotFoundMessage
return
if page == nil && !pageName.IsIndex {
// fallback to index
pageName, _ = model.ParsePageName("")
page = store.GetPageByName(pageName.String())
if page == nil {
response.Error = pageNotFoundMessage
return
}
}

// func: check if "Sign in required" response should be sent
Expand Down
30 changes: 27 additions & 3 deletions server/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,16 +99,40 @@ func Start(ctx context.Context, wg *sync.WaitGroup, serverPort int) {
router.NoRoute(func(c *gin.Context) {

if !strings.HasPrefix(c.Request.RequestURI, apiRoutePrefix+"/") {
urlPath := strings.TrimRight(c.Request.URL.Path, "/") + "/"
log.Debugln("Request path:", urlPath)
baseHref := strings.Trim(c.Request.URL.Path, "/")
log.Debugln("Request path:", baseHref)

if baseHref != "" {
hrefParts := strings.Split(baseHref, "/")
if len(hrefParts) > 1 {
baseHref = strings.Join(hrefParts[:2], "/")
if store.GetPageByName(baseHref) == nil {
// fallback to index page
baseHref = ""
}
} else {
baseHref = ""
}
}

if baseHref != "" {
baseHref = "/" + baseHref + "/"
} else {
baseHref = "/"
}

index, _ := assetsFS.Open(siteDefaultDocument)
indexData, _ := ioutil.ReadAll(index)

// base path
indexData = bytes.Replace(indexData,
[]byte("<base href=\"/\">"),
[]byte("<base href=\""+urlPath+"\">"), 1)
[]byte("<base href=\""+baseHref+"\">"), 1)

// route URL strategy
indexData = bytes.Replace(indexData,
[]byte("%FLET_ROUTE_URL_STRATEGY%"),
[]byte(config.RouteUrlStrategy()), 1)

// web renderer
if config.WebRenderer() != "" {
Expand Down