jczic / MicroWebSrv2

The last Micro Web Server for IoTs (MicroPython) or large servers (CPython), that supports WebSockets, routes, template engine and with really optimized architecture (mem allocations, async I/Os). Ready for ESP32, STM32 on Pyboard, Pycom's chipsets (WiPy, LoPy, ...). Robust, efficient and documented!
https://github.com/jczic/MicroWebSrv2
MIT License
656 stars 97 forks source link

How do I load .pyhtml templates? #22

Closed William04A closed 4 years ago

William04A commented 4 years ago

This may sound like a silly question - and it probably is, because I should have been able to get this to work by now.

I want/need to include a .pyhtml file in the application I am making. I looked in the source code, and the PyHTML extension should automatically send and render the template when I go to a page with the name of my PyHTML and .pyhtml in the end, correct?

So, if I have a file named "page.pyhtml", I should simply be able to visit /page.pyhtml? Because, that gives me a 404 error.

I have initialized the PyHTML addon and I have enabled debugging, but I did not get any output from the debugger.

jczic commented 4 years ago

Hello @William04A, For your first question, yes, it's right, you can try that in the demo. If you have the 404 not found error, it's because the server doesn't found the pyhtml file on physical path. Can you try the demo and check if the ...../test.pyhtml works please? (files must be in www folder by default).

William04A commented 4 years ago

I didn't realize the www folder... of course! But, I put two files in that folder: -page.pyhtml and -test.html

192.168.4.1/test.html - Returns 200 192.168.4.1/page.pyhtml - Returns 404

So I think that the path is no longer the issue.

jczic commented 4 years ago

Hello, Could you send me your code (main and page.pythml)? It's maybe a root path problem.

William04A commented 4 years ago

I am using your server for a product and cannot, therefore, disclose any code.

jczic commented 4 years ago

Ok, I understand and I thank you for that. But just, could you try the demo on your platform and check the test.pyhtml page who must be works because if the module is loaded, I don't understand why you got a not found error for the pyhtml file only...

bareynol commented 4 years ago

I've been getting some similar (but different) difficulties while trying to use pyhtml templates.

When RootPath is set to 'www', using a pyhtml template as the NotFoundUrl causes any request without a route to return a 403 Forbidden error, rather than redirecting to the pyhtml file. Only attempting the route /www/ will return the redirect.

Using a pyhtml file in AddDefaultPage also seems to cause 403 Forbidden on requests without a route.

Here's my code (/www/index.pyhtml exists on the device):

from MicroWebSrv2 import *
mws2 = MicroWebSrv2()
mws2.SetEmbeddedConfig()
pyhtmlTemplateMod = MicroWebSrv2.LoadModule('PyhtmlTemplate')
pyhtmlTemplateMod.ShowDebug = True
mws2.RootPath = "www"
mws2.NotFoundURL = "index.pyhtml"
mws2.StartManaged()

Here's the results of requests:

192.168.4.1/ -> 403 Forbidden 192.168.4.1/www/ -> 307 Temporary Redirect (to 192.168.4.1/index.pyhtml) 192.168.4.1/index.pyhtml -> 200 OK (loads properly)

If I try to use AddDefaultPage instead of NotFoundURL:

from MicroWebSrv2 import *
mws2 = MicroWebSrv2()
mws2.SetEmbeddedConfig()
pyhtmlTemplateMod = MicroWebSrv2.LoadModule('PyhtmlTemplate')
pyhtmlTemplateMod.ShowDebug = True
mws2.RootPath = "www"
mws2.AddDefaultPage('index.pyhtml')
mws2.StartManaged()

192.168.4.1/ -> 403 Forbidden 192.168.4.1/www/ -> 404 Not Found 192.168.4.1/index.pyhtml -> 200 OK (loads properly)

If I use an html file (test.html so as to not be caught by default configs) instead of a pyhtml file, then both NotFoundURL and AddDefaultPage work as expected where:

192.168.4.1/ -> 200 OK 192.168.4.1/www/ -> 307 temporary redirect (if using NotFoundURL, else 404) 192.168.4.1/test.html -> 200 OK

jczic commented 4 years ago

Hello @echolocation, Ok your results are normal because modules (like pyhtml) are not called for a default page :

bareynol commented 4 years ago

That explains a lot, thank you!

On Wed., Jan. 8, 2020, 7:34 p.m. J-Christophe Bos, notifications@github.com wrote:

Hello @echolocation https://github.com/echolocation, Ok your results are normal because modules (like pyhtml) are not called for a default page :

  • RootPath is the physical root path, so 192.168.4.1/www doesn't exists and is redirected if NotFoundURL is present.
  • 192.168.4.1/ is the root directory and 403 is returned if no html default page is present. If you really want that '/' processes a .pythml file, you must to handle '/' route and return a redirect to the .pythml file yourself. In effect, modules are processed before http routes and are not called for a specific file extension but when the request starts.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/jczic/MicroWebSrv2/issues/22?email_source=notifications&email_token=ABWJIDBVGMAXICCR2LPK2CDQ4ZWJLA5CNFSM4KB4I7ZKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEIOPYVI#issuecomment-572324949, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABWJIDAFE374QSW57ALQJIDQ4ZWJLANCNFSM4KB4I7ZA .

William04A commented 4 years ago

Ok, I understand and I thank you for that. But just, could you try the demo on your platform and check the test.pyhtml page who must be works because if the module is loaded, I don't understand why you got a not found error for the pyhtml file only...

Absolutely, I am doing that and getting back ASAP.

William04A commented 4 years ago

Running the demo and visiting /test.pyhtml gives me a 307 Temporary Redirect to the index page. I assume that is not expected...?

Initializing filesystem as FatFS!

       ---------------------------
       - Python pkg MicroWebSrv2 -
       -      version 2.0.6      -
       -     by JC`zic & HC2     -
       ---------------------------

 + [@WebRoute] GET /test-redir
 + [@WebRoute] GET /test-post (TestPost1/2)
 + [@WebRoute] POST /test-post (TestPost2/2)

MWS2-INFO> Server listening on 0.0.0.0:80.
MWS2-INFO> Starts the managed pool to wait for I/O events.
MWS2-DEBUG> From 192.168.4.2:27557 GET /robots.txt >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:27556 GET / >> [200] OK
MWS2-DEBUG> From 192.168.4.2:27556 GET /style.css >> [200] OK
MWS2-DEBUG> From 192.168.4.2:27556 GET /pdf.png >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:27559 GET /favicon.ico >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:27560 GET /test.pyhtml >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:27561 GET /pdf.png >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:27562 GET /favicon.ico >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:27563 GET /test.pyhtml >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:27564 GET /pdf.png >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:27565 GET /favicon.ico >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:27566 GET /test.pyhtml >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:27567 GET /pdf.png >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:27568 GET /favicon.ico >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:27571 GET /test.pyhtml >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:27572 GET /pdf.png >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:27573 GET /favicon.ico >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:27574 GET /test.pdf >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:27575 GET /pdf.png >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:27576 GET /favicon.ico >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:27578 GET /test.pyhtml >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:27577 GET /pdf.png >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:27580 GET /favicon.ico >> [307] Temporary Redirect

The example seems to 307 everything for me...

jczic commented 4 years ago

Ok I see and I don't understand why the first /style.css returns OK. Could you try to test files manually with the os.stat function like :

from os import stat
print(stat('/'))
print(stat('/www'))
print(stat('/www/style.css'))
print(stat('/www/pdf.png'))

There seems to be a problem reading the file size in the returned tuple. Thank you for your help to solve it :)

William04A commented 4 years ago
(16384, 0, 0, 0, 0, 0, 0, 959558400, 959558400, 959558400)
>>> print(stat("www"))
(16384, 0, 0, 0, 0, 0, 0, 315532810, 315532810, 315532810)
>>> print(stat("www/style.css"))
(32768, 0, 0, 0, 0, 0, 574, 315532862, 315532862, 315532862)
>>> print(stat("www/pdf.png"))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 2] ENOENT
>>> print(stat("/www/pdf.png"))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 19] ENODEV

I could not get to pdf.png for some reason, but it is under www/pdf.png on my device.

I am using a PyCom WiPy.

If I can help out with anything, tell me and I'll provide what you need.

jczic commented 4 years ago

Hmm, it seem that you have a problem with files... Do you have FTP access to check all files and folders? Maybe a chmod (right) problem? Note: style.css is a text file but no pdf.png. I have a WiPy too without this type of bug. Ensure that all files are correctly copied... You must have the same error if you enter stat("www/blabla.bla") right?

interconnectix commented 1 year ago

I am looking for some help trying to get the .pyhtml templates to load. I have read over everything I could find with no luck. With this configuration, it will 'download' the file to my machine '[200] OK' but won't render. What am I doing wrong?

I am trying to get the /testpy.pyhtml to load:

######################################## @WebRoute(GET, '/test') def RequestTest(microWebSrv2, request) : request.Response.ReturnOkJSON({ 'ClientAddr' : request.UserAddress, 'Accept' : request.Accept, 'UserAgent' : request.UserAgent })

@WebRoute(GET, '/testpy') def OnRequest(microWebSrv2, request) : request.Response.ReturnFile('/test.pyhtml') pass

mws2 = MicroWebSrv2() mws2.SetEmbeddedConfig() pyhtmlTemplateMod = MicroWebSrv2.LoadModule('PyhtmlTemplate') pyhtmlTemplateMod.ShowDebug = True mws2.RootPath = "/"

mws2.ConnQueueCapacity = 8

mws2._slotsCount = 4

mws2.BufferSlotsCount = 10

mws2.BufferSlotSize = 1024 mws2.KeepAllocBufferSlots = True mws2.MaxRequestContentLength = 16*1024 mws2.StartManaged()

Main program loop until keyboard interrupt,

try : while True : sleep(1) except KeyboardInterrupt : mws2.Stop()

interconnectix commented 1 year ago

Ok I got it figured out for anyone else that might come across this problem...

@WebRoute(GET, '/testpy') def OnRequest(microWebSrv2, request) : request.Response.ReturnRedirect('/test.pyhtml') pass

mws2 = MicroWebSrv2() mws2.SetEmbeddedConfig() pyhtmlTemplateMod = MicroWebSrv2.LoadModule('PyhtmlTemplate') pyhtmlTemplateMod.ShowDebug = True mws2.RootPath = "/"

mws2.ConnQueueCapacity = 8

mws2._slotsCount = 4

mws2.BufferSlotsCount = 10

mws2.BufferSlotSize = 1024 mws2.KeepAllocBufferSlots = True mws2.MaxRequestContentLength = 16*1024 mws2.StartManaged()

try : while True : sleep(1) except KeyboardInterrupt : mws2.Stop()

jczic commented 1 year ago

Hi @interconnectix, indeed, ReturnFile(...) returns a file as a response but not a page to process. The .pyhtml files are processed automatically when they correspond directly to a route. If you want to manually return a .pyhtml file yourself, you would have to directly call the function of the module that processes the file to transcribe it into content and then return that content.

interconnectix commented 1 year ago

Hi @jczic, what would you recommend then for code to call the function directly? I am currently using a redirect using routes.

jczic commented 1 year ago

And using the routes is the normal and easiest way :) Only if you have special needs it can be useful to process the pyhtml content directly.