Page 1 of 1
ReceiveHTTPMemory
Posted: Tue Mar 04, 2025 10:56 pm
by williamvanhoecke
Hello,
The following lines is returning a *Buffer while it should return 0 (the URL exists but the map BUTTONS does not)
The buffer in memory contains
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
<p>Additionally, a 404 Not Found
error was encountered while trying to use an ErrorDocument to handle the request.</p>
</body></html>
Am i doing somthing wrong here ?
Code: Select all
Define *Buffer = ReceiveHTTPMemory("Https://www.listrik.be/BUTTONS/my-test-image.png", #PB_HTTP_NoRedirect)
If *Buffer
ProcedureReturn *Buffer
Else
ProcedureReturn EncodeImage(LoadImage(#PB_Any,exe_path + "BUTTONS/schakelaar.png"), #PB_ImagePlugin_PNG)
EndIf
Re: ReceiveHTTPMemory
Posted: Tue Mar 04, 2025 11:09 pm
by Bisonte
first : You see that there is no file with that name on this url. so it cannot be downloaded.
second: why you are using EncodeImage ? (if the download was correct) You have a png file, so CatchImage() to get the image and SaveImage() to save it...
so UsePNGImageEncoder and Decoder is needed...
Edit :
Code: Select all
UsePNGImageDecoder()
UseJPEGImageDecoder()
*Buffer = ReceiveHTTPMemory(URLEncoder("https://www.listrik.be/eendraadschema index_htm_files/81.jpg"), #PB_HTTP_NoRedirect)
If *Buffer
Image = CatchImage(#PB_Any, *Buffer)
If IsImage(Image)
Debug "Image Ok"
EndIf
Else
Image = LoadImage(#PB_Any, exe_path.s + "BUTTONS/schakelaar.png")
EndIf
Re: ReceiveHTTPMemory
Posted: Tue Mar 04, 2025 11:29 pm
by williamvanhoecke
Hi, thanks for your reply
the calling routine is
Code: Select all
DrawImage(ImageID(CatchImage(#PB_Any,get_image())),0,0)
If the image is found then a it is in memory
If not found on the server the image is loaded locally from disk and the put in memory.
in both cases I return a pointer to the catchimage routine.
But that is not the problem, the
If *Buffer always fires even if the file is not found.... normally the ]Buffer should be 0
Re: ReceiveHTTPMemory
Posted: Wed Mar 05, 2025 7:45 am
by Bisonte
williamvanhoecke wrote: Tue Mar 04, 2025 11:29 pm
If *Buffer always fires even if the file is not found.... normally the ]Buffer should be 0
It is "guilty" because there is something in this *Buffer... Image or not. Now it is on the developer to do something with it.
Thats why I try to use "Catchimage". This is the test, if it is a 404 HTTP Error (or something else) or an Image.
Re: ReceiveHTTPMemory
Posted: Wed Mar 05, 2025 4:14 pm
by Thorium
williamvanhoecke wrote: Tue Mar 04, 2025 11:29 pm
But that is not the problem, the
If *Buffer always fires even if the file is not found.... normally the ]Buffer should be 0
It is correct that it is not 0. The server is sending back a HTML file to display the error message on a browser. That is typical behavior of web servers as they expect a browser to fetch the file and need a way to show the user what wend wrong.
You need to parse the HTML to determine if the file exists.
First check the size of the returned buffer. Then you can check the title tag. If the first characters are "<title>" you can assume it's not a png file but a html response from the server.
Re: ReceiveHTTPMemory
Posted: Thu Mar 06, 2025 10:34 pm
by williamvanhoecke
Thanks thorium,
I already worked around like below.
Code: Select all
Procedure.i GetImagePointer(File.s)
Define *Buffer = ReceiveHTTPMemory("https://www.listrik.be/ListrikTheme/" + File, #PB_HTTP_NoRedirect)
If FindString(PeekS(*Buffer, MemorySize(*Buffer), #PB_UTF8), "404 Not Found") > 0
Debug LoadImage(#PB_Any,exe_path + "BUTTONS/" + GetFilePart(File))
ProcedureReturn EncodeImage(LoadImage(#PB_Any,exe_path + "BUTTONS/" + GetFilePart(File)), #PB_ImagePlugin_PNG)
Else
ProcedureReturn *Buffer
EndIf
EndProcedure
Still, I think this is a bug, I would expect the 'ReceiveHTTPMemory()' function to do the check and return a valid pointer or 0
Re: ReceiveHTTPMemory
Posted: Fri Mar 07, 2025 1:07 am
by williamvanhoecke
Bisonte wrote: Wed Mar 05, 2025 7:45 am
williamvanhoecke wrote: Tue Mar 04, 2025 11:29 pm
If *Buffer always fires even if the file is not found.... normally the ]Buffer should be 0
It is "guilty" because there is something in this *Buffer... Image or not. Now it is on the developer to do something with it.
Thats why I try to use "Catchimage". This is the test, if it is a 404 HTTP Error (or something else) or an Image.
Yes, I know now, I found out by testing and checking, but documentation says otherwise, is says to check if the returned memorypointer = 0 or not ->
"Returns the new memory buffer address if the download was successful, zero otherwise."
Re: ReceiveHTTPMemory
Posted: Fri Mar 07, 2025 1:18 am
by kenmo
ReceiveHTTPMemory() is giving you the exact data it received from the server... I think it's OK as-is.
You can go one step further and check the HTTP StatusCode, here is a helper function:
Code: Select all
Procedure.i ReceiveHTTPMemoryStrict(URL.s, Flags.i = 0, UserAgent.s = "")
Protected *Buffer = #Null
If (UserAgent = "")
UserAgent = "Mozilla/5.0 Gecko/41.0 Firefox/41.0" ; default per ReceiveHTTPMemory() help
EndIf
NewMap Headers.s()
Headers("User-Agent") = UserAgent
Protected Req.i = HTTPRequest(#PB_HTTP_Get, URL, "", Flags, Headers())
If (Req)
Select (Val(HTTPInfo(Req, #PB_HTTP_StatusCode)))
Case 200 To 299 ; Success
*Buffer = HTTPMemory(Req)
EndSelect
FinishHTTP(Req)
EndIf
ProcedureReturn (*Buffer)
EndProcedure
URL.s = "Https://www.listrik.be/BUTTONS/my-test-image.png"
;URL.s = "https://www.listrik.be/eendraadschema index_htm_files/81.jpg"
;URL.s = "https://www.purebasic.com/img/pb-logo-white.png"
*Buffer = ReceiveHTTPMemoryStrict(URL, #PB_HTTP_NoRedirect)
If *Buffer
ShowMemoryViewer(*Buffer, MemorySize(*Buffer))
CallDebugger
FreeMemory(*Buffer)
Else
Debug "Failed"
EndIf
Re: ReceiveHTTPMemory
Posted: Fri Mar 07, 2025 11:15 am
by NicTheQuick
williamvanhoecke wrote: Tue Mar 04, 2025 11:29 pm
the calling routine is
Code: Select all
DrawImage(ImageID(CatchImage(#PB_Any,get_image())),0,0)
Are you aware that this is a memory leak?
`CatchImage(#PB_Any, ...)` returns a freshly created object that is never stored in a variable. So you will never be able to use `FreeImage()` with it. So if that line is executed more than once your memory consumption will increase which each iteration.
Re: ReceiveHTTPMemory
Posted: Fri Mar 07, 2025 2:34 pm
by Kiffi
kenmo wrote: Fri Mar 07, 2025 1:18 amReceiveHTTPMemory() is giving you the exact data it received from the server... I think it's OK as-is.
+1
Re: ReceiveHTTPMemory
Posted: Fri Mar 07, 2025 11:23 pm
by williamvanhoecke
NicTheQuick wrote: Fri Mar 07, 2025 11:15 am
williamvanhoecke wrote: Tue Mar 04, 2025 11:29 pm
the calling routine is
Code: Select all
DrawImage(ImageID(CatchImage(#PB_Any,get_image())),0,0)
Are you aware that this is a memory leak?
`CatchImage(#PB_Any, ...)` returns a freshly created object that is never stored in a variable. So you will never be able to use `FreeImage()` with it. So if that line is executed more than once your memory consumption will increase which each iteration.
Thanks for your concern, and yes I am aware of the memory consumption, but it is about images that are there as long as the program lives.
Re: ReceiveHTTPMemory
Posted: Sat Mar 08, 2025 12:03 am
by williamvanhoecke
kenmo wrote: Fri Mar 07, 2025 1:18 am
ReceiveHTTPMemory() is giving you the exact data it received from the server... I think it's OK as-is.
You can go one step further and check the HTTP StatusCode, here is a helper function:
Code: Select all
Procedure.i ReceiveHTTPMemoryStrict(URL.s, Flags.i = 0, UserAgent.s = "")
Protected *Buffer = #Null
If (UserAgent = "")
UserAgent = "Mozilla/5.0 Gecko/41.0 Firefox/41.0" ; default per ReceiveHTTPMemory() help
EndIf
NewMap Headers.s()
Headers("User-Agent") = UserAgent
Protected Req.i = HTTPRequest(#PB_HTTP_Get, URL, "", Flags, Headers())
If (Req)
Select (Val(HTTPInfo(Req, #PB_HTTP_StatusCode)))
Case 200 To 299 ; Success
*Buffer = HTTPMemory(Req)
EndSelect
FinishHTTP(Req)
EndIf
ProcedureReturn (*Buffer)
EndProcedure
URL.s = "Https://www.listrik.be/BUTTONS/my-test-image.png"
;URL.s = "https://www.listrik.be/eendraadschema index_htm_files/81.jpg"
;URL.s = "https://www.purebasic.com/img/pb-logo-white.png"
*Buffer = ReceiveHTTPMemoryStrict(URL, #PB_HTTP_NoRedirect)
If *Buffer
ShowMemoryViewer(*Buffer, MemorySize(*Buffer))
CallDebugger
FreeMemory(*Buffer)
Else
Debug "Failed"
EndIf
Ok... nice code
I would expect to do al this checking stuff with
HTTPRequestMemory()
The
ReceiveHTTPMemory() however is explicitly to receive a pointer to a file, not some other stuff the server decides to send, so i would expect the function itself to do the checking and return an valid pointer or 0.
I was just mislead by the documentation:
Returns nonzero if the download was successful, zero otherwise
Simply solved it like this
Code: Select all
Procedure.i MyReceiveHTTPMemory(url.s)
Define *Buffer = ReceiveHTTPMemory(url, #PB_HTTP_NoRedirect)
If *Buffer = 0 Or FindString(PeekS(*Buffer, MemorySize(*Buffer), #PB_UTF8), "404 Not Found") > 0
Retun 0
else
ProcedureReturn *Buffer
EndIf
EndProcedure