Question Carl Campbell · Jun 18, 2021

Sending a PDF file in a REST Message

Hi Community...I am trying figure this out any help appreciated. Thanks in advance

The service is a file passthrough that picks up a  PDF and then uses the BPL  code below to create the rest wrapper and sends the stream data. I am not grabbing the stream from the inbound correctly,  "request.Stream" or "request.StreamFC" always produces the following  error.

Here is what is sent and returned in the message..

request:

<Stream>

15@%Library.FileCharacterStream

</Stream>

response:

<Stream>

Unable to load xml from message: Data at the root level is invalid. Line 1, position 1.

</Stream>

-I think my issue is I am not using the right class by using "%GlobalStreamCharacter",  Or the raw PDF CDATA inbound I am not handling correctly

  set context.RESTMessage.Stream=##class(%GlobalCharacterStream).%New() 

I have tried using different Stream types...File, Binary....but no luck

-The general BPL below

/// BPL Definition
XData BPL [ XMLNamespace = "http://www.intersystems.com/bpl]
{
<process language='objectscript' request='Ens.StreamContainer' response='Ens.Response' height='2000' width='2000' >
<context>

.....

.....

....

<code name='Create REST Message' xpos='200' ypos='250' >
<![CDATA[
   set context.RESTMessage=##class(EnsLib.HTTP.GenericMessage).%New()
   set context.RESTMessage.Stream=##class(%GlobalCharacterStream).%New()
   set tSC=context.RESTMessage.Stream.Write(request.StreamFC)
   set tSC=context.RESTMessage.HTTPHeaders.SetAt("application/xml","Content-Type")
   set tSC=context.RESTMessage.HTTPHeaders.SetAt(context.RESTMessage.Stream.Size,"Content-Length")
   set tSC=context.RESTMessage.HTTPHeaders.SetAt("POST","HttpRequest")
    
   
   ]]>
</code>

Comments

Eduard Lebedyuk · Jun 18, 2021

Please post your <call> block which utilizes context.RESTMessage

0
Carl Campbell  Jun 18, 2021 to Eduard Lebedyuk

Thanks for response...

<call name='To <application> Rest' target='To<application>REST' async='0' xpos='200' ypos='350' >
<request type='EnsLib.REST.GenericMessage>
<assign property="callrequestvalue="context.RESTMessageaction="set" />
</request>
<response type='EnsLib.REST.GenericMessage>
<assign property="context.RESTResponsevalue="callresponseaction="set" />
</response>
</call>

0
Eduard Lebedyuk  Jun 18, 2021 to Carl Campbell

Try to send it like this:

<call name='To application Rest' target='To application REST' async='0'>
  <request type='EnsLib.REST.GenericMessage' >
    <assign property="status"  value='callrequest.Stream.CopyFrom(request.StreamFC)' action="set" />
    <assign property="status"  value='callrequest.HTTPHeaders.SetAt("application/xml", "Content-Type")' action="set" />
    <assign property="status"  value='callrequest.HTTPHeaders.SetAt(callrequest.Stream.Size, "Content-Length")' action="set" />
    <assign property="status"  value='callrequest.HTTPHeaders.SetAt("POST", "HttpRequest")' action="set" />
  </request>
</call>

Also I think you can skip Content-Length - it's appended to the request automatically.

0
Carl Campbell  Jun 18, 2021 to Eduard Lebedyuk

Thanks for response... im getting the error below on my BPL Log

ERROR <Ens>ErrBPTerminated: Terminating BP <APPLICATION>BPL # due to error: ERROR <Ens>ErrException: <INVALID OREF>zS1+13^<APPLICATION>BPL.Thread1.1 -- logged as '-' number - @' Set status=1,status=callrequest.Stream.CopyFrom(request.StreamFC)' > ERROR <Ens>ErrException: <INVALID OREF>zS1+13^<APPLICATION>.Thread1.1 -- logged as '-' number - @' Set status=1,status=callrequest.Stream.CopyFrom(request.StreamFC)'

0
Eduard Lebedyuk  Jun 18, 2021 to Carl Campbell

This way then:

<call name='To application Rest' target='To application REST' async='0'>
  <request type='EnsLib.REST.GenericMessage' >
    <assign property="callrequest.Stream" value='##class(%Stream.GlobalCharacter).%New()'/>
    <assign property="status"  value='callrequest.Stream.CopyFrom(request.StreamFC)' action="set" />
    <assign property="status"  value='callrequest.HTTPHeaders.SetAt("application/xml", "Content-Type")' action="set" />
    <assign property="status"  value='callrequest.HTTPHeaders.SetAt(callrequest.Stream.Size, "Content-Length")' action="set" />
    <assign property="status"  value='callrequest.HTTPHeaders.SetAt("POST", "HttpRequest")' action="set" />
  </request>
</call>
0
Carl Campbell  Jun 18, 2021 to Eduard Lebedyuk

This does the trick with regards to that now I can see the same inbound data within the  Ens.Container stream data is exactly what is passed down stream...That is good. There are no more references to "15@%Library.FileCharacterStream
". BUT  I still have this error 

<Stream>

Unable to load xml from message: Data at the root level is invalid. Line 1, position 1.

</Stream>

The message going downstream within the stream property starts out like this "<GenericMessage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:s="http://www.w3.org/2001/XMLSchema">

<Stream>

<![CDATA[%PDF-1.6

" which i believe is appropriate for raw pdf data. (This I will research).

Thanks for the help I will work on this more. My best guess at this point is to review how the PDF is being encoded and what the expectation is on the downstream. The reference to line 1 position one might refer to the "%" character in my stream. Maybe the downstream expects something more similiar to 

"<?XML...."

Thanks Again

0