B4J Question Creating a proxy

somed3v3loper

Well-Known Member
Licensed User
Longtime User
Hello all ,

I asked this question in a server thread but as per Erel's request I am reposting the question as a new thread .

Can a server download file from internet and send it to client ?
I am thinking of making a small proxy .
What I tried is getting url from client in a handler class then download the file (http job) when job finishes I use File.Copy2(job.GetInputStream , ...) to write to resp.OutputStream .
But as you can see Sub Handle(req As ServletRequest, resp As ServletResponse) should have finished at that time


Thanks in advance
 

Roycefer

Well-Known Member
Licensed User
Longtime User
I'm not sure if this will work, but you could put the resp object in the HttpJob's Tag property. This would allow you to retrieve it in the JobDone() event and then write to its OutputStream.

Another untested idea would be to use the Lock object from the Threading library. It will look something like this:
B4X:
'Handler class
Sub Class_Globals
   Dim l As Lock
   Dim inp As InputStream
End Sub

Public Sub Initialize
   l.Initialize(True)  'Lock is initialized as locked
End Sub

Sub Handle(req As ServletRequest, resp As ServletResponse)
'    Get the url from req
'    Create and initiate the HttpJob
    l.Wait    'Execution will stop here until the Lock is released in JobDone
    File.Copy2(inp, resp.OutputStream)    'This can only happen after the Lock has been released
'   call Job.Release on the HttpJob here, after you are done with its InputStream
End Sub

Sub JobDone(Job As HttpJob)
    inp = Job.GetInputStream
    l.Unlock
End Sub
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
The above code will not work.

Correct code:
B4X:
Sub Class_Globals
  Private mResp As ServletResponse
End Sub

Public Sub Initialize
 
End Sub

Sub Handle(req As ServletRequest, resp As ServletResponse)
mResp = resp
Dim j As HttpJob
j.Initialize("j", Me)
j.Download(...)
StartMessageLoop '<----------
End Sub

Sub JobDone(Job As HttpJob)
If Job.Success Then
  File.Copy2(Job.GetInputStream, mResp.OutputStream)
Else
  resp.SendError(500, Job.ErrorMessage)
End If
StopMessageLoop '<---------
End Sub
 
Last edited:
Upvote 0

somed3v3loper

Well-Known Member
Licensed User
Longtime User
Thanks Roycefer I tried the first idea and before trying threading one , Erel posted his solution .

The above code will not work.

Correct code:
B4X:
Sub Class_Globals
  Private mResp As ServletResponse
End Sub

Public Sub Initialize
 
End Sub

Sub Handle(req As ServletRequest, resp As ServletResponse)
mResp = resp
Dim j As HttpJob
j.Initialize(Me, "j")
j.Download(...)
StartMessageLoop '<----------
End Sub

Sub JobDone(Job As HttpJob)
If Job.Success Then
  File.Copy2(Job.GetInputStream, mResp.OutputStream)
Else
  resp.SendError(500, Job.ErrorMessage)
End If
StopMessageLoop '<---------
End Sub

Thanks a lot that works but it seems that server downloads file and then make it available to client can we have something like streaming the file .
Please correct me if I misunderstood how it works .
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Change hc_ResponseSuccess tp:
B4X:
Sub hc_ResponseSuccess (Response As HttpResponse, TaskId As Int)
   Dim job As HttpJob = TaskIdToJob.Get(TaskId)
   Dim resp As ServletResponse = job.Tag
   Response.GetAsynchronously("response", resp.OutputStream, False, TaskId)
End Sub

Make sure to set Job.Tag before the download.
 
Upvote 0

somed3v3loper

Well-Known Member
Licensed User
Longtime User
Change hc_ResponseSuccess tp:
B4X:
Sub hc_ResponseSuccess (Response As HttpResponse, TaskId As Int)
   Dim job As HttpJob = TaskIdToJob.Get(TaskId)
   Dim resp As ServletResponse = job.Tag
   Response.GetAsynchronously("response", resp.OutputStream, False, TaskId)
End Sub

Make sure to set Job.Tag before the download.

Will this work for browsing webpages ?

Youtube is not working for me.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
You need to understand how web pages work.

Pages, especially complex pages like YouTube, are not made of a single request. The first request returns the page html. The html page includes references to other external resources. The browser downloads all the resources and runs the javascript. The javascript can create many more requests.
The browser should be configured to send all the requests to the proxy server. The proxy server should

Your solution only handles the first request. It can be useful for file downloads.
 
Upvote 0

somed3v3loper

Well-Known Member
Licensed User
Longtime User
You need to understand how web pages work.

Pages, especially complex pages like YouTube, are not made of a single request. The first request returns the page html. The html page includes references to other external resources. The browser downloads all the resources and runs the javascript. The javascript can create many more requests.
The browser should be configured to send all the requests to the proxy server. The proxy server should

Your solution only handles the first request. It can be useful for file downloads.

Thanks for this information .
Yes I might use this for downloading files but can we get a full proxy that serve webpages too ?
I think it might be done differently but do not know how ?
And if there is already a java library to wrap and use with B4J .
 
Upvote 0
Top