Handleurl WebResponse.file vs WebRequest.file change since 2021r1

Starting in 2020r1, in the HandleURL event, there is a new response argument (WebResponse class). It has a file property to return a file. Previously, this had to be done using the request.file.

In 2021r1 and 2021r1.1, response.File does not work anymore. Using response.file returns a generic 404 page (I assume provided by the Xojo framework). You have to revert using request.file which, strangely, works.

Try the following to serve png files on your desktop. In the App.HandleURL event:

if Request.Path.right(4) <> ".png" then return false

response.File = SpecialFolder.Desktop.Child(Request.Path)
response.Status = 200
response.Header("Content-Type") = "image/png"
response.Header("Content-Disposition") = "attachment; filename=" + Request.Path
return true

Exception
  return False

You can request a png using http://127.0.0.1:8080/myfile.png (assuming you have a png named myfile.png on your desktop)

In 2021r1 (and 2021r1.1), you will get a 404 page
In 2020r2.1, it works fine.

If you replace response.file by request.file, then it works in 2021r1 and 2021r1.1, as well as 2020r2.1

Am I missing something? Or is it a regression? If anyone has insights on this before I open a feedback case (which I searched beforehand this time :grin:).

Sounds like a bug that’s never fixed…?

I don’t think it’s an old bug that never got corrected. Before 2020r1, you would send a file using “request.file = myfile” and it worked. When 2020r1 was released, there was a new WebResponse class to separate the request from the response, which makes a lot of sense. HandleURL now has both a request and response parameters. It’s more logical to say “response.file = myfile” to send a file as part of the response. I converted our api backend to the new framework and compiled it with 2020r1 and it worked. So no bug at that time.

Fast forward to now, facing the memory leaks and temporary file buildups, I was excited to recompile with 2021r1.1. It did fix both problems but then sending files suddenly stopped working. Which led to my investigation … and findings :slight_smile: My workaround was to go back to using “request.file = myfile” which, strangely, works perfectly in 2021r1.1.

I do not have 2020r1 installed and I did not test with every release after that to find the exact one where the problem first appeared. But I would rather call it a recently introduced bug, not an old unfixed one.

Anyways, if anyone has experienced this, please chime in!

So working through your code I think I see what the problem is…

First of all, you are passing a path to Folderitem.Child where it only takes a Name. Passing a path which contains a / character changes the path to a filename and the file ends up being Nil.

I’ve modified your code to support paths:

If Request.Path.Right(4) <> ".png" Then Return False

Dim f As FolderItem = SpecialFolder.Desktop
Dim pathParts() As String = Request.Path.Split("/")
Try
  For i As Integer = 0 To UBound(pathparts)
    f = f.Child(pathParts(i))
  Next i
Catch ex As NilObjectException
  Return False
End Try

response.File = f
response.Status = 200
response.MIMEType = "image/png"

Return True

Exception e
  Return False

See if that works better for you

2 Likes

Hi Greg. Thanks for looking into this, I really appreciate it. You’re right that if I pass a full path in the URL, the folderitem is invalid.

However, I’m not passing a full path, I only put the filename in the URL. This was a simple test that only supported files directly on the desktop. The URL I used was
http://127.0.0.1:8080/myfile.png
I have checked the actual folderitem in debug to make sure it was pointing to a valid file.

For good measure, I tried hardcoding the filename and returning a different response (not found) if any exception is raised with a status code of 200. This way, the app should never return a 404 even if an exception is raised.

response.Status = 200
response.File = SpecialFolder.Desktop.Child("minions.png")
response.Header("Content-Type") = "image/png"
response.Header("Content-Disposition") = "attachment; filename=" + "minions.png"
return true

Exception
  response.Status = 200
  response.write "An exception occured"
  return true

Running this has the same result: receiving a 404 page.

I added the UnhandledException event to the app, and there is in fact an unhandled exception raised. That’s where the 404 page comes from, not from the code itself in HandleURL. Here’s the stack:

RuntimeRaiseException
RaiseNilObjectException
WebResponse._TransferBuffer%o<_WebFileBuffer>%o<WebResponse>
WebRequest._Apply%%o<WebRequest>o<WebResponse>
WebApplication._HandleDeveloperRequest%b%o<WebApplication>o<_HTTPServer.HTTPRequestContext>
WebApplication._HandleHTTPRequest%%o<WebApplication>o<_HTTPServer.HTTPRequestContext>
_HTTPServer.HTTPRequestThread.Event_Run%%o<_HTTPServer.HTTPRequestThread>
rbframework.dylib$6234
rbframework.dylib$5962
_pthread_start

So maybe that can help locate the source of the bug.
I can send a sample project with great pleasure.

Thanks again for any help!

Did you try it without the Content-Disposition header ?

response.Status = 200
// Are you 100% sure xojo/your app has access to the desktop ?
response.File = SpecialFolder.Desktop.Child("minions.png")
response.mimeType = "image/png"
return true

Exception
  response.Status = 200
  response.write "An exception occured"
  return true

Good points, Dirk, thanks for taking some time to help.

Did you try it without the Content-Disposition header ?

Yes. I just tried again to be sure. This only makes the browser (most of the time) save the file instead of displaying it.

Are you 100% sure xojo/your app has access to the desktop ?

Yes. Also, in the first code I posted I built the folderitem and assigned it to a variable and then checked its content in debug to see if it was valid and existed. It did.

Remember the exact same code works in 2020.

I’d be curious to see any example of code in HandleURL using response=file that runs successfully in 2021. Has anyone tried?

Using the sample code results in getting nothing for me too. If I make the suggested change, which is shared below, the file is returned via the browser as expected.

If Request.Path.Right(4) <> ".png" Then Return False

Request.File = SpecialFolder.Desktop.Child(Request.Path)
Response.Status = 200
Response.Header("Content-Type") = "image/png"
Response.Header("Content-Disposition") = "attachment; filename=" + Request.Path
Return True

Exception
Return False

Looks like a bug in 2021r1.1.

Response.File = SpecialFolder.Desktop.Child(Request.Path) should work but does not.
Request.File = SpecialFolder.Desktop.Child(Request.Path) works but should not.

How about the code I posted above? I checked that code in 2021r1.1 and it works fine, regardless of whether the path is a path or just a file name.

FWIW, the Content-Disposition header you are setting is identical to what we do internally.

I suggest trying the MimeType property instead of just setting the Content-Type header.

Thanks Greg. I’ll definitely use MimeType, it’s cleaner.

I created a new empty web project and I tried your code and it doesn’t work. Now I’m really baffled :upside_down_face:

Maybe there’s something in my environment? I’m on MacOS 11.2.3, MacBook Pro 2019 Intel. No plugins other that the default Xojo ones. Anything else you think I should be looking for?

Hi @Greg_O_Lone

I tried your sample code and it does not work for me with a clean install of Xojo 2021r1.1 on macOS 11.3.1. If I replace response with request for the file, which I’ve shared below, it works.

If Request.Path.Right(4) <> ".png" Then Return False

Dim f As FolderItem = SpecialFolder.Desktop
Dim pathParts() As String = Request.Path.Split("/")
Try
  For i As Integer = 0 To UBound(pathparts)
    f = f.Child(pathParts(i))
  Next i
Catch ex As NilObjectException
  Return False
End Try

request.File = f
response.Status = 200
response.MIMEType = "image/png"

Return True

Exception e
  Return False

Any idea why response is failing for Bruno and I but not you? MD5 is 141ebb4849fc952710c3eec76baae262 for /Applications/Xojo 2021 Release 1.1/Xojo.app/Contents/MacOS/Xojo on my system.

My MD5 is the same as Fred’s: 141ebb4849fc952710c3eec76baae262

@Greg_O_Lone It should also be noted that Bruno and I are both running Big Sur. We’re running different versions of Big Sur but are both on macOS 11.x. I’m on 11.3.1 and Bruno is on 11.2.3. If the three of us are all using the same Xojo binary and are all on Big Sur, the differences in behavior will be be even more puzzling.

Additional info: my final project runs on 3 different Mac Minis, two are on MacOS 10.15.7 and one is on 10.13.6. All 3 showed the same problem with response.file and for all 3, changing response to request fixed it. They all use a compiled app.

<https://xojo.com/issue/64740>

Fixed.

Awesome Greg! Thank you for your time and help.

Thanks Greg!