@@ -13,12 +13,14 @@ use actix_web::{
1313} ;
1414use sqlpage:: {
1515 app_config:: { test_database_url, AppConfig } ,
16+ filesystem:: DbFsQueries ,
1617 webserver:: {
1718 self ,
1819 http:: { form_config, main_handler, payload_config} ,
1920 } ,
2021 AppState ,
2122} ;
23+ use sqlx:: Executor as _;
2224
2325#[ actix_web:: test]
2426async fn test_index_ok ( ) {
@@ -695,6 +697,74 @@ async fn test_failed_copy_followed_by_query() -> actix_web::Result<()> {
695697 Ok ( ( ) )
696698}
697699
700+ #[ actix_web:: test]
701+ async fn test_routing_with_db_fs_and_prefix ( ) {
702+ let mut config = test_config ( ) ;
703+ config. site_prefix = "/prefix/" . to_string ( ) ;
704+ let state = AppState :: init ( & config) . await . unwrap ( ) ;
705+
706+ // Set up database filesystem
707+ let create_table_sql = DbFsQueries :: get_create_table_sql ( state. db . connection . any_kind ( ) ) ;
708+ state
709+ . db
710+ . connection
711+ . execute ( format ! ( "DROP TABLE IF EXISTS sqlpage_files; {create_table_sql}" ) . as_str ( ) )
712+ . await
713+ . unwrap ( ) ;
714+
715+ // Insert test file into database
716+ sqlx:: query ( "INSERT INTO sqlpage_files(path, contents) VALUES ('tests/sql_test_files/it_works_simple.sql', 'SELECT ''It works !'' as message;')" )
717+ . execute ( & state. db . connection )
718+ . await
719+ . unwrap ( ) ;
720+
721+ let app_data = actix_web:: web:: Data :: new ( state) ;
722+
723+ // Test basic routing with prefix
724+ let resp = req_path_with_app_data (
725+ "/prefix/tests/sql_test_files/it_works_simple.sql" ,
726+ app_data. clone ( ) ,
727+ )
728+ . await
729+ . unwrap ( ) ;
730+ assert_eq ! ( resp. status( ) , http:: StatusCode :: OK ) ;
731+ let body = test:: read_body ( resp) . await ;
732+ let body_str = String :: from_utf8 ( body. to_vec ( ) ) . unwrap ( ) ;
733+ assert ! (
734+ body_str. contains( "It works !" ) ,
735+ "{body_str}\n expected to contain: It works !"
736+ ) ;
737+ assert ! (
738+ body_str. contains( "href=\" /prefix/" ) ,
739+ "{body_str}\n expected to contain links with site prefix"
740+ ) ;
741+
742+ // Test 404 handling with prefix
743+ let resp = req_path_with_app_data ( "/prefix/nonexistent.sql" , app_data. clone ( ) )
744+ . await
745+ . expect_err ( "Expected 404 error" )
746+ . to_string ( ) ;
747+ assert ! ( resp. contains( "404" ) ) ;
748+
749+ // Test forbidden paths with prefix
750+ let resp = req_path_with_app_data ( "/prefix/sqlpage/migrations/0001_init.sql" , app_data. clone ( ) )
751+ . await
752+ . expect_err ( "Expected forbidden error" )
753+ . to_string ( ) ;
754+ assert ! ( resp. to_lowercase( ) . contains( "forbidden" ) , "{resp}" ) ;
755+
756+ // accessing without prefix should redirect to the prefix
757+ let resp = req_path_with_app_data ( "/tests/sql_test_files/it_works_simple.sql" , app_data)
758+ . await
759+ . unwrap ( ) ;
760+ assert_eq ! ( resp. status( ) , http:: StatusCode :: MOVED_PERMANENTLY ) ;
761+ let location = resp
762+ . headers ( )
763+ . get ( "location" )
764+ . expect ( "location header should be present" ) ;
765+ assert_eq ! ( location. to_str( ) . unwrap( ) , "/prefix/" ) ;
766+ }
767+
698768async fn get_request_to_with_data (
699769 path : & str ,
700770 data : actix_web:: web:: Data < AppState > ,
@@ -752,7 +822,12 @@ async fn req_path_with_app_data(
752822 let resp = tokio:: time:: timeout ( REQ_TIMEOUT , main_handler ( req) )
753823 . await
754824 . map_err ( |e| anyhow:: anyhow!( "Request to {path} timed out: {e}" ) ) ?
755- . map_err ( |e| anyhow:: anyhow!( "Request to {path} failed: {e}" ) ) ?;
825+ . map_err ( |e| {
826+ anyhow:: anyhow!(
827+ "Request to {path} failed with status {}: {e:#}" ,
828+ e. as_response_error( ) . status_code( )
829+ )
830+ } ) ?;
756831 Ok ( resp)
757832}
758833
0 commit comments