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>

0
0 288
Discussion (6)1
Log in or sign up to continue

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

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>

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.

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)'

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>

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