Anyway, the code above should work fine as tested by WRC. You can use HttpRequest.Post(tURL, 1, 1) to just display the request on the current device and compare it with the request sent by Postman, if there are any differences.
If you are a supported customer (with the license under support - SUTA), please contact WRC. More details you can find at https://www.intersystems.com/support/
Please, what is definition of your stream property and how do you create its data?
If the stream is type of %Library.GlobalCharacterStream or %Library.GlobalBinaryStream, the location of the streams depends if you write data directly to the stream property or if you created the stream first and assign it to stream property:
Class tv.test Extends %Persistent, { Property MyStream As %GlobalCharacterStream; }
I have tried to test your code and found the Content-Length was set to 0 when ContentCharset was set.
I investigated that it was cased by the code reading the data before Posting to server, therefore the EntityBody stream was at end and calculated size after translation to UTF-8 was zero.
To fix it you need to rewind the stream before you send it using Post() method:
set httpRequest.ContentType = "application/json" set httpRequest.ContentCharset="utf-8" ...
Do httpRequest.EntityBody.Write(body.%ToJSON()) while(httpRequest.EntityBody.AtEnd=0){ set linea = httpRequest.EntityBody.Read() }
Do httpRequest.EntityBody.Rewind() //REWIND the data to start from the beginning after reading !!! $$$LOGINFO("linea: "_linea) set tSC = httpRequest.Post("https://onesignal.com/api/v1/notifications") set tResponse = httpRequest.HttpResponse
Could you please provide more details? Are you creating SOAP WebService in Caché and want to return stream data? Or is it a SOAP client connecting to some external webservice?
Generally for WebService you define return type as %Stream.GlobalCharacter, then create and fill the stream object and that's it.
Example of web method returning stream data:
Method GetStream(text As %String) As %Stream.GlobalCharacter [ WebMethod ] { set stream=##class(%Stream.GlobalCharacter).%New() Do stream.WriteLine("First Line") Do stream.WriteLine("Second Line") Do stream.WriteLine("Last Line with Text: "_text) Quit stream } Is this what you are looking for?
I think the solution is to use character stream and made manual Base64Encoding/Decoding.
I have created two methods for it:
/// Flags - 0 - Insert CR/LF after every 76 characters (Default)<br> /// Flags - 1 - Do not insert CR/LF after every 76 characters.<br> ClassMethod Base64Encode(tIn As %Stream.TmpBinary, Output tOut As %Stream.TmpCharacter, chunk As %Integer = 32000, Flags As %Integer = 1) As %Status { set sc = $$$OK if $g(tIn)="" quit $$$ERROR(5001, "Input stream required") if '$IsObject(tIn) quit $$$ERROR(5001,"Input is not a stream object") if 'tIn.%IsA("%Stream.Object") quit $$$ERROR(5001,"Input object is not a stream") If '$IsObject($g(tOut)) { set tOut=##class(%Stream.TmpCharacter).%New() } if 'tOut.%IsA("%Stream.Object") quit $$$ERROR(5001,"Output object is not a stream") set chunk=chunk-(chunk#3) do tIn.Rewind() While 'tIn.AtEnd { set sc= tOut.Write($SYSTEM.Encryption.Base64Encode(tIn.Read(chunk),Flags)) if 'sc Quit } Quit sc }
ClassMethod Base64Decode(tIn As %Stream.TmpBinary, Output tOut As %Stream.TmpCharacter, chunk As %Integer = 32000) As %Status { set sc = $$$OK if $g(tIn)="" quit $$$ERROR(5001,"Input stream required") if '$IsObject(tIn) quit $$$ERROR(5001,"Input is not a stream object") if 'tIn.%IsA("%Stream.Object") quit $$$ERROR(5001,"Input object is not a stream") If '$IsObject($g(tOut)) { set tOut=##class(%Stream.TmpCharacter).%New() } if 'tOut.%IsA("%Stream.Object") quit $$$ERROR(5001,"Output object is not a stream") set chunk=chunk-(chunk#4) do tIn.Rewind() While 'tIn.AtEnd { set sc= tOut.Write($SYSTEM.Encryption.Base64Decode(tIn.Read(chunk))) if 'sc Quit } Quit sc }
Then in the code you need to call it e.g.:
set sc = ..Base64Encode(tPDF,tDocRequest.FileContent,,1)
where 'tPDF' is a stream object with original PDF content, tDocRequest.FileContent then will contain given PDF encoded to Base64 - this is what binary streams do automatically.
This is not version nor index, it is part of the routine name. Each class compiles at the routines. There is always <classname>.0 routine with class descriptor (always only as .OBJ code), where it holds the information what code it should run for particular property/method.
It then generates number of routines with generated code. For most classes there is only one - <classname>.1
If incremental compile is detected, it does not recreate <classname>.1 routine but creates a new routine <classname>.2 with the new code and updates the class descriptor to reflect it.
All this discussion is only for upgrades/conversions of 8-bit instances, which use NLS locale based on different charset than Latin1 (ISO 8859-1).
Upgrade from 8-bit Caché to Unicode is trivial if 8-bit instance is using NLS locale based on Latin1 charset. In such case the upgrade is only installing the Unicode version over the 8-bit instance. This is because first 0-255 characters of Unicode are same as Latin1 charset, therefore no conversion is needed.
Of course, customer should check if all his interfaces support Unicode, eventually configure it properly (e.g. use correct driver for unix ODBC client).
What also matter is how CSP Gateway in Apache is set. E.g. Caché Private Apache webserver is set to serve all files from Caché (directive CSP On), therefore it is served by Caché server and depends on settings of corresponding CSP application on Caché server side.
Right, this is exactly what UnescapeHTML method does:
/// This method converts Escaped HTML text into normal HTML text ClassMethod UnescapeHTML(in) As %String [ CodeMode = expression, ServerOnly = 1 ] { $zconvert(in,"I","HTML") }
I looked at the generated code (I made my own example) and it is:
s i%AKI=$g(^CODE("TNO",i%Type,i%MyID,"AKI"))
Therefore as Robert already wrote, it is option 1). The property is empty (has empty string) if given node doesn't exist or is set to "". And from object point you cannot differentiate it.
Even using %ObjectIsNull method you would get same result if the global is killed or if it is set to "".
Export which applications? * => 6 Export which types of applications (1=CSP,2=Routine,3=Executable)? * => Export to file name ApplicationsExport.xml => Parameters? "WNS" => Confirm export of Applications records to ApplicationsExport.xml? No => yes Export of 1 applications records complete
The most probably you would need also to enable LoginFailure audit event in Security > Auditing > Configure System Events. LoginFailure is used to log details about the "Access Denied" event. Then reproduce a problem and look for details of LoginFailure record in View Audit Database.
Please, don't use the deprecated class definition classes from %Library package (like %ClassDefinition, %ProperyDefinition etc) but use ones from %Dictionary package. The On-Line Documentation for %Library.*Definition and %Library.Compiled* classes state:
Note: The class definition classes in the %Library package have been superseded by those in the %Dictionary package.
What I see as a problem is the Caché version you mentioned - 2017.2.2 (Build 865U_SU) is SingleUser version, available as download for evaluation purposes. It is not meant for development/production purposes. It also doesn't allow to enter a Caché license key, it has built-in license with single user there.
So I would recommend to contact your InterSystems Sales Rep. or WRC to get the full installation kit for Caché 2017.2.2.
go to post
It was solved by WRC (InterSystems Support).
Anyway, the code above should work fine as tested by WRC. You can use HttpRequest.Post(tURL, 1, 1) to just display the request on the current device and compare it with the request sent by Postman, if there are any differences.
go to post
If you are a supported customer (with the license under support - SUTA), please contact WRC. More details you can find at https://www.intersystems.com/support/
go to post
Please, what is definition of your stream property and how do you create its data?
If the stream is type of %Library.GlobalCharacterStream or %Library.GlobalBinaryStream, the location of the streams depends if you write data directly to the stream property or if you created the stream first and assign it to stream property:
{
Property MyStream As %GlobalCharacterStream;
}
USER>s x=##class(tv.test).%New()
USER>w x.MyStream.%Location
^tv.testS
USER>w x.MyStream.Write("My Data")
1
USER>w x.%Save()
1
USER>zw x.MyStream.GetStreamId()
$lb($c(0,16,1,11,1)_"^tv.testS"_$c(3,4,4,2,1),"%GlobalCharacterStream"
BUT:
USER>s x=##class(tv.test).%New()
USER>s str=##class(%GlobalCharacterStream).%New()
USER>w str.%Location
^CacheStream
USER>s x.MyStream=str
USER>w x.MyStream.%Location
^CacheStream
USER>w x.MyStream.Write("My Data")
1
USER>w x.%Save()
1
USER>zw x.MyStream.GetStreamId()
$lb($c(0,19,1,14,1)_"^CacheStream"_$c(3,4,2,2,1),"%GlobalCharacterStream")
Therefore if you do not want to change the location of the stream, is better to use CopyFrom method insterad:
USER>s x=##class(tv.test).%New()
USER>s str=##class(%GlobalCharacterStream).%New()
USER>w str.Write("My Data")
1
USER>w x.MyStream.CopyFrom(str)
1
USER>w x.%Save()
1
USER>zw x.MyStream.GetStreamId()
$lb($c(0,16,1,11,1)_"^tv.testS"_$c(3,4,5,2,1),"%GlobalCharacterStream")
Please, let us know if it corresponds to your findings.
go to post
Yone, try to set ContentCharset AFTER setting of ContentType:
set httpRequest.ContentType = "application/json"
set httpRequest.ContentCharset = "UTF-8"
This is from %Net.HttpRequest class documentation:
property ContentCharset as %String [ Calculated ];
Will it change anything?
go to post
I have tried to test your code and found the Content-Length was set to 0 when ContentCharset was set.
I investigated that it was cased by the code reading the data before Posting to server, therefore the EntityBody stream was at end and calculated size after translation to UTF-8 was zero.
To fix it you need to rewind the stream before you send it using Post() method:
set httpRequest.ContentCharset="utf-8"
...
set linea = httpRequest.EntityBody.Read()
}
Do httpRequest.EntityBody.Rewind() //REWIND the data to start from the beginning after reading !!!
$$$LOGINFO("linea: "_linea)
set tSC = httpRequest.Post("https://onesignal.com/api/v1/notifications") set tResponse = httpRequest.HttpResponse
Does it help?
go to post
If ID is numeric...
go to post
Could you please provide more details? Are you creating SOAP WebService in Caché and want to return stream data? Or is it a SOAP client connecting to some external webservice?
Generally for WebService you define return type as %Stream.GlobalCharacter, then create and fill the stream object and that's it.
Example of web method returning stream data:
{
set stream=##class(%Stream.GlobalCharacter).%New()
Do stream.WriteLine("First Line")
Do stream.WriteLine("Second Line")
Do stream.WriteLine("Last Line with Text: "_text)
Quit stream
}
Is this what you are looking for?
go to post
I think the solution is to use character stream and made manual Base64Encoding/Decoding.
I have created two methods for it:
/// Flags - 1 - Do not insert CR/LF after every 76 characters.<br>
ClassMethod Base64Encode(tIn As %Stream.TmpBinary, Output tOut As %Stream.TmpCharacter, chunk As %Integer = 32000, Flags As %Integer = 1) As %Status
{
set sc = $$$OK
if $g(tIn)="" quit $$$ERROR(5001, "Input stream required")
if '$IsObject(tIn) quit $$$ERROR(5001,"Input is not a stream object")
if 'tIn.%IsA("%Stream.Object") quit $$$ERROR(5001,"Input object is not a stream")
If '$IsObject($g(tOut)) {
set tOut=##class(%Stream.TmpCharacter).%New()
}
if 'tOut.%IsA("%Stream.Object") quit $$$ERROR(5001,"Output object is not a stream")
set chunk=chunk-(chunk#3)
do tIn.Rewind()
While 'tIn.AtEnd {
set sc= tOut.Write($SYSTEM.Encryption.Base64Encode(tIn.Read(chunk),Flags))
if 'sc Quit
}
Quit sc
}
ClassMethod Base64Decode(tIn As %Stream.TmpBinary, Output tOut As %Stream.TmpCharacter, chunk As %Integer = 32000) As %Status
{
set sc = $$$OK
if $g(tIn)="" quit $$$ERROR(5001,"Input stream required")
if '$IsObject(tIn) quit $$$ERROR(5001,"Input is not a stream object")
if 'tIn.%IsA("%Stream.Object") quit $$$ERROR(5001,"Input object is not a stream")
If '$IsObject($g(tOut)) {
set tOut=##class(%Stream.TmpCharacter).%New()
}
if 'tOut.%IsA("%Stream.Object") quit $$$ERROR(5001,"Output object is not a stream")
set chunk=chunk-(chunk#4)
do tIn.Rewind()
While 'tIn.AtEnd {
set sc= tOut.Write($SYSTEM.Encryption.Base64Decode(tIn.Read(chunk)))
if 'sc Quit
}
Quit sc
}
Then in the code you need to call it e.g.:
where 'tPDF' is a stream object with original PDF content, tDocRequest.FileContent then will contain given PDF encoded to Base64 - this is what binary streams do automatically.
go to post
This is not version nor index, it is part of the routine name. Each class compiles at the routines. There is always <classname>.0 routine with class descriptor (always only as .OBJ code), where it holds the information what code it should run for particular property/method.
It then generates number of routines with generated code. For most classes there is only one - <classname>.1
If incremental compile is detected, it does not recreate <classname>.1 routine but creates a new routine <classname>.2 with the new code and updates the class descriptor to reflect it.
go to post
What kind of "type" do you want to get? The system variable $PRINCIPAL gives you current device.
For Terminal:
USER>Write $PRINCIPAL |TRM|:|14516
For Telnet:
USER>Write $PRINCIPAL |TNT|CZ-LAT5520VAVER.iscinternal.com:52971|21608
go to post
IMPORTANT NOTE:
All this discussion is only for upgrades/conversions of 8-bit instances, which use NLS locale based on different charset than Latin1 (ISO 8859-1).
Upgrade from 8-bit Caché to Unicode is trivial if 8-bit instance is using NLS locale based on Latin1 charset. In such case the upgrade is only installing the Unicode version over the 8-bit instance. This is because first 0-255 characters of Unicode are same as Latin1 charset, therefore no conversion is needed.
Of course, customer should check if all his interfaces support Unicode, eventually configure it properly (e.g. use correct driver for unix ODBC client).
go to post
This is a absolute path to your webserver. The URLs for given css and js files are:
http://<webserver>/jbsscan/stylesheets/style.css
http://<webserver>/jbsscan/javascript/javascriptScanner.js
The location depends on the definition of the DocumentRoot in your Apache httpd.conf. E.g. for following example
DocumentRoot "c:/Apache24/htdocs"
the files should be located in following folders
C:\Apache24\htdocs\jbsscan\stylesheets\
C:\Apache24\htdocs\jbsscan\javascript\
What also matter is how CSP Gateway in Apache is set. E.g. Caché Private Apache webserver is set to serve all files from Caché (directive CSP On), therefore it is served by Caché server and depends on settings of corresponding CSP application on Caché server side.
go to post
Another way:
set number="",$p(number,0,4)=1 w number 0001
go to post
Right, this is exactly what UnescapeHTML method does:
ClassMethod UnescapeHTML(in) As %String [ CodeMode = expression, ServerOnly = 1 ]
{
$zconvert(in,"I","HTML")
}
go to post
I looked at the generated code (I made my own example) and it is:
Therefore as Robert already wrote, it is option 1). The property is empty (has empty string) if given node doesn't exist or is set to "". And from object point you cannot differentiate it.
Even using %ObjectIsNull method you would get same result if the global is killed or if it is set to "".
Question is why do you need such information?
go to post
Steve, what do you mean by "the property is defined"? Property is always defined if you make it in the class definition.
On object side you can only check whether property is empty or has some other value.
IF myobject.AKI="" { do some other stuff ...}
But you do not know if it is because ^CODE("TNO","BIO",291,"AKI")= "" or if it doesn't exist.
go to post
Yes, there is a way using ^SECURITY routine in %SYS namespace in Terminal.
You can export single application or all of them.
USER>zn "%SYS"
%SYS>d ^SECURITY
1) User setup
2) Role setup
3) Service setup
4) Resource setup
5) Application setup
6) Auditing setup
7) Domain setup
8) SSL configuration setup
9) Mobile phone service provider setup
10) OpenAM Identity Services setup
11) Encryption key setup
12) System parameter setup
13) X509 User setup
14) KMIP server setup
15) Exit
Option? 5
1) Create application
2) Edit application
3) List applications
4) Detailed list applications
5) Delete application
6) Export applications
7) Import applications
8) Exit
Option? 6
Export which applications? * => ?
Num Name Namespace
1) /api/atelier %SYS
2) /api/deepsee %SYS
3) /api/iknow %SYS
4) /csp/ensdemo ENSDEMO
5) /csp/ensemble ENSEMBLE
6) /csp/samples SAMPLES
7) /csp/samples/docserver SAMPLES
8) /csp/user USER
9) /isc/studio/usertemplates %SYS
10) /csp/broker %SYS
11) /csp/docbook DOCBOOK
12) /csp/documatic DOCBOOK
13) /csp/sys %SYS
14) /csp/sys/bi %SYS
15) /csp/sys/exp %SYS
16) /csp/sys/mgr %SYS
17) /csp/sys/op %SYS
18) /csp/sys/sec %SYS
19) /isc/pki %SYS
20) /isc/studio/rules %SYS
21) /isc/studio/templates %SYS
Export which applications? * => 6
Export which types of applications (1=CSP,2=Routine,3=Executable)? * =>
Export to file name ApplicationsExport.xml =>
Parameters? "WNS" =>
Confirm export of Applications records to ApplicationsExport.xml? No => yes
Export of 1 applications records complete
go to post
The most probably you would need also to enable LoginFailure audit event in Security > Auditing > Configure System Events. LoginFailure is used to log details about the "Access Denied" event. Then reproduce a problem and look for details of LoginFailure record in View Audit Database.
go to post
Hi Gevorg,
Please, don't use the deprecated class definition classes from %Library package (like %ClassDefinition, %ProperyDefinition etc) but use ones from %Dictionary package. The On-Line Documentation for %Library.*Definition and %Library.Compiled* classes state:
Note: The class definition classes in the %Library package have been superseded by those in the %Dictionary package.
Thank you.
go to post
Hi, there is also archive of older checklist available in same documentation, so you can check what changed since version 2013.1 and if it affects your application - https://docs.intersystems.com/cache20172/csp/docbook/DocBook.UI.Page.cls...
What I see as a problem is the Caché version you mentioned - 2017.2.2 (Build 865U_SU) is SingleUser version, available as download for evaluation purposes. It is not meant for development/production purposes. It also doesn't allow to enter a Caché license key, it has built-in license with single user there.
So I would recommend to contact your InterSystems Sales Rep. or WRC to get the full installation kit for Caché 2017.2.2.