@@ -74,7 +74,7 @@ def __init__(self, wifi_ssid, wifi_password, port=80, timeout=20, doc_root="/www
7474 async def start_server (self ):
7575 print ("start_server" )
7676 server_task = asyncio .create_task (asyncio .start_server (
77- self .serve_request , "0.0.0.0" , 80 ))
77+ self .serve_request , "0.0.0.0" , self . port ))
7878 await server_task
7979
8080 # async def start_server(self):
@@ -90,6 +90,7 @@ def add_function_route(self, route, function):
9090 async def serve_request (self , reader , writer ):
9191 gc .collect ()
9292 try :
93+ response = Response (writer )
9394 url = ""
9495 method = ""
9596 content_length = 0
@@ -130,9 +131,26 @@ async def serve_request(self, reader, writer):
130131 if content_length > 0 :
131132 post_data_raw = await reader .readexactly (content_length )
132133 print ("POST data:" , post_data_raw )
133- post_data = json .loads (post_data_raw )
134+ content_type_header = "Content-Type: application/json" # default to JSON
135+ for header in headers :
136+ if header .lower ().startswith ("content-type:" ):
137+ content_type_header = header
138+ break
139+ if "application/json" in content_type_header .lower ():
140+ try :
141+ post_data = json .loads (post_data_raw )
142+ except ValueError as e :
143+ print ("Error decoding JSON data:" , e )
144+ # Handle the error (e.g., send an error response to the client)
145+ await response .send ("Invalid JSON data" , status_code = 400 )
146+ return
147+ elif "application/x-www-form-urlencoded" in content_type_header .lower ():
148+ post_data = self .parse_form_data (post_data_raw .decode ('utf-8' ))
149+ else :
150+ # Handle unsupported content types
151+ await response .send ("Unsupported content type" , status_code = 415 )
152+ return
134153 request = Request (post_data )
135- response = Response (writer )
136154 # check if the url is a function route and if so run the function
137155 path_components = self .get_path_components (url )
138156 print ("path_components: " + str (path_components ))
@@ -147,26 +165,50 @@ async def serve_request(self, reader, writer):
147165 if self .log_level > 0 :
148166 print ("file_path: " + str (file_path ))
149167 # if uos.stat(file_path)[6] > 0:
150- if self .file_exists (file_path ):
168+ if self .file_exists (file_path ): #serve a file
151169 content_type = self .get_content_type (url )
152170 if self .log_level > 1 :
153171 print ("content_type: " + str (content_type ))
154172 await response .send_file (file_path , content_type = content_type )
155173 return
156- if url == "/" :
157- print ( "root" )
158- files_and_folders = self .list_files_and_folders (self . doc_root )
174+ # perhaps it is a folder
175+ if self . dir_exists ( file_path ): #serve a folder
176+ files_and_folders = self .list_files_and_folders (file_path )
159177 await response .send_iterator (self .generate_root_page_html (files_and_folders ))
160178 return
161- html = self .generate_root_page_html (files_and_folders )
162- await response .send (html )
163- return
179+ # if url == "/":
180+ # print("root")
181+ # files_and_folders = self.list_files_and_folders(self.doc_root)
182+ # await response.send_iterator(self.generate_root_page_html(files_and_folders))
183+ # return
164184 print ("file not found " + url )
165185 await response .send (self .html % "page not found " + url , status_code = 404 )
166186 if (url == "/shutdown" ):
167187 self .serving = False
168188 except OSError as e :
169189 print (e )
190+
191+ def parse_form_data (self , form_data_raw ):
192+ form_data = {}
193+ for pair in form_data_raw .split ('&' ):
194+ key , value = pair .split ('=' )
195+ form_data [self .url_decode (key )] = self .url_decode (value )
196+ return form_data
197+
198+ def url_decode (self , encoded_str ):
199+ decoded_str = ""
200+ i = 0
201+ while i < len (encoded_str ):
202+ if encoded_str [i ] == '%' :
203+ hex_code = encoded_str [i + 1 :i + 3 ]
204+ char = chr (int (hex_code , 16 ))
205+ decoded_str += char
206+ i += 3
207+ else :
208+ decoded_str += encoded_str [i ]
209+ i += 1
210+ return decoded_str
211+
170212
171213 def dir_exists (self , filename ):
172214 try :
@@ -304,9 +346,14 @@ def blink_element(element, pin, duration=0.27):
304346 await asyncio .sleep (delay_between_digits if element != '.' else 2 * delay_between_digits )
305347 await asyncio .sleep (delay_between_repititions )
306348
349+
307350 def list_files_and_folders (self , path ):
308351 entries = uos .ilistdir (path )
309352 files_and_folders = []
353+ # print("list_files_and_folders: "+path)
354+ # print("list_files_and_folders: "+self.doc_root)
355+ if path != self .doc_root and path != self .doc_root + '/' :
356+ files_and_folders .append ({"name" : ".." , "type" : "directory" })
310357 for entry in entries :
311358 name = entry [0 ]
312359 mode = entry [1 ]
@@ -331,29 +378,31 @@ def generate_root_page_html(self, files_and_folders):
331378 <div class="relative flex min-h-screen flex-col justify-center overflow-hidden bg-gray-50 py-6 sm:py-12">
332379 <div class="relative bg-white px-6 pb-8 pt-10 shadow-xl ring-1 ring-gray-900/5 sm:mx-auto sm:max-w-lg sm:rounded-lg sm:px-10">
333380 <div class="mx-auto max-w-md">
334- <img src="/img/logo.svg" class="h-12 w-auto" alt="GurgleApps.com">
381+ <a href="https://gurgleapps.com">< img src="/img/logo.svg" class="h-12 w-auto" alt="GurgleApps.com"></a >
335382 """
336383 yield """
337384 <div class="divide-y divide-gray-300/50">
338385 <div class="space-y-6 py-8 text-base leading-7 text-gray-600">
339386 <h1 class="text-lg font-semibold">Welcome to GurgleApps.com Webserver</h1>
340387 <h12 class="text-base font-semibold">File List:</h2>
341- <ul class="space-y-2 mt-3">
388+ <ul class="mt-3">
342389 """
343390 folder_icon_svg = """
344- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-6 h-6 fill-indigo-800 ">
391+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-6 h-6">
345392 <path d="M19.5 21a3 3 0 003-3v-4.5a3 3 0 00-3-3h-15a3 3 0 00-3 3V18a3 3 0 003 3h15zM1.5 10.146V6a3 3 0 013-3h5.379a2.25 2.25 0 011.59.659l2.122 2.121c.14.141.331.22.53.22H19.5a3 3 0 013 3v1.146A4.483 4.483 0 0019.5 9h-15a4.483 4.483 0 00-3 1.146z" />
346393 </svg>
347394 """
348395 file_icon_svg = """
349- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-6 h-6 fill-indigo-800 ">
396+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-6 h-6">
350397 <path d="M5.625 1.5c-1.036 0-1.875.84-1.875 1.875v17.25c0 1.035.84 1.875 1.875 1.875h12.75c1.035 0 1.875-.84 1.875-1.875V12.75A3.75 3.75 0 0016.5 9h-1.875a1.875 1.875 0 01-1.875-1.875V5.25A3.75 3.75 0 009 1.5H5.625z" />
351398 <path d="M12.971 1.816A5.23 5.23 0 0114.25 5.25v1.875c0 .207.168.375.375.375H16.5a5.23 5.23 0 013.434 1.279 9.768 9.768 0 00-6.963-6.963z" />
352399 </svg>
353400 """
354- for file_or_folder in files_and_folders :
355- icon = folder_icon_svg if file_or_folder ['type' ] == 'directory' else file_icon_svg
356- yield f"<li class='border-t pt-1'><a href='/{ file_or_folder ['name' ]} ' class='flex items-center font-semibold text-slate-800 hover:text-indigo-800'>{ icon } <p class='ml-2'>{ file_or_folder ['name' ]} </p></a></li>"
401+ for index , file_or_folder in enumerate (files_and_folders ):
402+ icon = folder_icon_svg if file_or_folder ['type' ] == 'directory' else file_icon_svg
403+ text_class = 'text-blue-500' if file_or_folder ['type' ] == 'directory' else 'text-blue-600'
404+ bg_class = "" if index % 2 == 1 else "bg-gray-50"
405+ yield f"<li class='border-t border-gray-300 py-1.5 { bg_class } '><a href='/{ file_or_folder ['name' ]} ' class='flex items-center font-semibold { text_class } hover:text-blue-700'>{ icon } <p class='ml-2'>{ file_or_folder ['name' ]} </p></a></li>"
357406 yield "</ul>"
358407 # Closing tags for the body and container div
359408 yield """
0 commit comments