11.6 PAS Web Transport

Posted by sbbe83 on 19-Apr-2016 15:59

Hi All,

I am trying to create a sample Web application using the PAS Web Transport and I have a couple of questions.

So far I have a WebHandler class that implements Progress.Web.IWebHandler and I am able to get a basic web request to go through and output a very simple HTML page. You can see the sample below. 

So onto my questions:

1.) How can I get POST data if said request was submitted via a form? I see I can get URI data from the URI property on the WebRequest but I am at a loss on how to get anything outside of this. In traditional WebSpeed I would just use get-value but I do not see anything similar to this.

2.)  This may be answered in #1 but if a file is uploaded via a form is this something that can be grabbed as well? In traditional WebSpeed you get use the get-binary-data but I am not able to verify this works as of yet so I want to make sure I am going to right directions.

Thanks for you time.
Chris Ebbs

/* SAME WEBHANDLER CLASS */
routine-level on error undo, throw.

class System.WebHandler implements Progress.Web.IWebHandler:

method public integer HandleRequest( ):
def var poRequest as class OpenEdge.Web.WebRequest no-undo.
def var poResponse as class OpenEdge.Web.WebResponse no-undo.
def var poResponseWriter as class OpenEdge.Web.WebResponseWriter no-undo.

poRequest = new OpenEdge.Web.WebRequest().
poResponse = new OpenEdge.Web.WebResponse().
poResponseWriter = new OpenEdge.Web.WebResponseWriter( poResponse ).

poResponse:SetHeader("Content-Type", "text/html").

poResponseWriter:Open().
poResponseWriter:Write('<html><body><h1>This is a test</h1></body></html>').
poResponseWriter:Flush().
poResponseWriter:Close().

delete object poRequest.
delete object poResponse.
delete object poResponseWriter.

return 0.
end method.

end class.

Posted by Peter Judge on 20-Apr-2016 07:36

1.) How can I get POST data if said request was submitted via a form? I see I can get URI data from the URI property on the WebRequest but I am at a loss on how to get anything outside of this. In traditional WebSpeed I would just use get-value but I do not see anything similar to this.

The WebRequest object contains the entire incoming request, regardless of how it was made (ie what the HTTP method was, what the message body is etc).
 
The Entity property is what you're after. It contains the message body if one exists, usually as a set of raw bytes. This is returned to you as an instance of OpenEdge.Core.Memptr; the exceptions being JSON and XML, which are returned as objects of type Progress.Json.ObjectModel.JsonConstruct and OpenEdge.Core.WidgetHandle resp). The JSON and XML conversions are done only for a particular set of values in the Content-Type header.
 
You can convert the raw bytes to a more useful objects using a set of classes known as EntityWriters: these take the body-in-bytes  and create a new, more strongly-typed entity object.
 
Take a look at the following snippet. There are a couple of important aspects
1. You can use  GetHeader or the ContentType property to determine the incoming request's payload. Also you can set the response's ContentType this way.
 
2.  The EntityWriterBuilder:Build line is what gets the appropriate writer. It conforms to a standard interface/API so you can call all of them the same way.
 
3. The EntityWriter's Entity property is also defined as Progress.Lang.Object. You will need to check either the ContentType or the object's type (via TYPE-OF , say) to determine what to cast the object to to make it more useful.
 
define variable iEmpNum as integer no-undo.
define variable oEntity as MultipartEntity no-undo.
define variable oPart as MessagePart no-undo.
define variable oEntityWriter as MessageWriter no-undo.
define variable oHeader as HttpHeader no-undo.
define variable cImageFileName as character no-undo.
       
oHeader = poRequest:GetHeader('Content-Type').
oHeader:ParamDelimiter = ';':u.
oHeader:ExtractParameters().
                                          
/* URL is /web/img/Employee/{EmpNum} */
assign iEmpNum = integer(poRequest:GetPathParameter('EmpNum':u))
       oEntityWriter = EntityWriterBuilder:Build(poRequest)
                                :Writer.
oEntityWriter:Open().
oEntityWriter:Write(poRequest:Entity).
oEntityWriter:Close().
       
assign oEntity = cast(oEntityWriter:Entity, MultipartEntity)
       oPart   = oEntity:GetPart(1)
       oHeader = oPart:Headers:Get('Content-Disposition':u)
              
       /* Content-Disposition: form-data; name="myphoto.png"; filename="emp_21.png" */
       cImageFileName = oHeader:GetParameterValue('filename':u).
 
moBE:WriteEmployeePic(iEmpNum,
                                    cImageFileName,
                                    cast(oPart:Body, ByteBucket):GetBytes()).
 
 
There's API doc at https://documentation.progress.com/output/oehttpclient/ that may be helpful.
 

2.)  This may be answered in #1 but if a file is uploaded via a form is this something that can be grabbed as well? In traditional WebSpeed you get use the get-binary-data but I am not able to verify this works as of yet so I want to make sure I am going to right directions.

Yes; follow the same approach as above.
 
 

All Replies

Posted by Irfan on 19-Apr-2016 16:08

For "form"  kind of applications, you can consider using "MultipartEntity" which can get the headers, path parameter and the body

oEntityWriter = EntityWriterBuilder:Build(poRequest)

                               :Writer.

       oEntityWriter:Open().

       oEntityWriter:Write(poRequest:Entity).

       oEntityWriter:Close().

      assign oEntity = cast(oEntityWriter:Entity, MultipartEntity)

      oPart   = oEntity:GetPart(1)

 // Gets header

      oHeader = oPart:Headers:Get('Content-Disposition':u).

       mediaType = oPart:ContentType.

  // Gets the Path Parameter

       empNum = Integer(poRequest:GetPathParameter("CUSTID")).

 // Gets body which is a binary

       memptr1 = cast(oPart:Body,ByteBucket):GetBytes().

Posted by Peter Judge on 20-Apr-2016 07:36

1.) How can I get POST data if said request was submitted via a form? I see I can get URI data from the URI property on the WebRequest but I am at a loss on how to get anything outside of this. In traditional WebSpeed I would just use get-value but I do not see anything similar to this.

The WebRequest object contains the entire incoming request, regardless of how it was made (ie what the HTTP method was, what the message body is etc).
 
The Entity property is what you're after. It contains the message body if one exists, usually as a set of raw bytes. This is returned to you as an instance of OpenEdge.Core.Memptr; the exceptions being JSON and XML, which are returned as objects of type Progress.Json.ObjectModel.JsonConstruct and OpenEdge.Core.WidgetHandle resp). The JSON and XML conversions are done only for a particular set of values in the Content-Type header.
 
You can convert the raw bytes to a more useful objects using a set of classes known as EntityWriters: these take the body-in-bytes  and create a new, more strongly-typed entity object.
 
Take a look at the following snippet. There are a couple of important aspects
1. You can use  GetHeader or the ContentType property to determine the incoming request's payload. Also you can set the response's ContentType this way.
 
2.  The EntityWriterBuilder:Build line is what gets the appropriate writer. It conforms to a standard interface/API so you can call all of them the same way.
 
3. The EntityWriter's Entity property is also defined as Progress.Lang.Object. You will need to check either the ContentType or the object's type (via TYPE-OF , say) to determine what to cast the object to to make it more useful.
 
define variable iEmpNum as integer no-undo.
define variable oEntity as MultipartEntity no-undo.
define variable oPart as MessagePart no-undo.
define variable oEntityWriter as MessageWriter no-undo.
define variable oHeader as HttpHeader no-undo.
define variable cImageFileName as character no-undo.
       
oHeader = poRequest:GetHeader('Content-Type').
oHeader:ParamDelimiter = ';':u.
oHeader:ExtractParameters().
                                          
/* URL is /web/img/Employee/{EmpNum} */
assign iEmpNum = integer(poRequest:GetPathParameter('EmpNum':u))
       oEntityWriter = EntityWriterBuilder:Build(poRequest)
                                :Writer.
oEntityWriter:Open().
oEntityWriter:Write(poRequest:Entity).
oEntityWriter:Close().
       
assign oEntity = cast(oEntityWriter:Entity, MultipartEntity)
       oPart   = oEntity:GetPart(1)
       oHeader = oPart:Headers:Get('Content-Disposition':u)
              
       /* Content-Disposition: form-data; name="myphoto.png"; filename="emp_21.png" */
       cImageFileName = oHeader:GetParameterValue('filename':u).
 
moBE:WriteEmployeePic(iEmpNum,
                                    cImageFileName,
                                    cast(oPart:Body, ByteBucket):GetBytes()).
 
 
There's API doc at https://documentation.progress.com/output/oehttpclient/ that may be helpful.
 

2.)  This may be answered in #1 but if a file is uploaded via a form is this something that can be grabbed as well? In traditional WebSpeed you get use the get-binary-data but I am not able to verify this works as of yet so I want to make sure I am going to right directions.

Yes; follow the same approach as above.
 
 

Posted by Peter Judge on 20-Apr-2016 08:30

And so the follow-up question to this will surely be: what's the type of a form-data-based Entity?
 
And the answer, sadly, is that we didn't get to providing one yet. It'l be string/string map or similar, but it's not there yet.
 
 

Posted by sbbe83 on 20-Apr-2016 08:51

Thanks for all the help, that worked so far. I see now how this works, it would be nice for a form-based entity but for now I can use the API to get around most of the issues.

This thread is closed