Zinc-Seaside: Problem with POSTing UTF-8 JSON

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
15 messages Options
Reply | Threaded
Open this post in threaded view
|

Zinc-Seaside: Problem with POSTing UTF-8 JSON

Tomas Kukol
Hi Sven.

I've had a problem when POSTing non-ascii UTF-8 characters in JSON to Seaside REST service. I've located the problem in the method ZnZincServerAdaptor>>requestBodyFor: where the body of ZnRequest is translated to body of WARequest. I use Pharo 1.4 with Seaside 3.0.8 and Zinc-Seaside-SvenVanCaekenberghe.40.

When the POSTed JSON contains non-ascii UTF-8 characters (Czech characters), they are corrupted. The problem is on the "MARKED" line, where the array of bytes changed to string by asString.

"Problematic" code:

ZnZincServerAdaptor>>requestBodyFor: aZincRequest
^ (aZincRequest method ~= #TRACE 
and: [ aZincRequest hasEntity
and: [ aZincRequest entity isEmpty not
and: [ (aZincRequest entity contentType matches: ZnMimeType applicationFormUrlEncoded) not
and: [ (aZincRequest entity contentType matches: ZnMimeType multiPartFormData) not ] ] ] ])
ifTrue: [
"Seaside wants to do its own text conversions"
aZincRequest entity bytes asString "MARKED" ]
ifFalse: [
String new ]

I did a quick correction, which is not nice, but works for me:

ZnZincServerAdaptor>>requestBodyFor: aZincRequest
^ (aZincRequest method ~= #TRACE 
and: [ aZincRequest hasEntity
and: [ aZincRequest entity isEmpty not
and: [ (aZincRequest entity contentType matches: ZnMimeType applicationFormUrlEncoded) not
and: [ (aZincRequest entity contentType matches: ZnMimeType multiPartFormData) not ] ] ] ])
ifTrue: [
"Seaside wants to do its own text conversions"
ZnUTF8Encoder new decodeBytes: aZincRequest entity bytes "CORRECTED" ]
ifFalse: [
String new ]

My correction tries to decode byte array with ZnUTF8Encoder and the result is OK.

Maybe I would recommend to use GRPharoUtf8Codec (although I like ZnUTF8Encoder more) or even better self codec (self = ZnZincServerAdaptor) to try to decode the bytes.

Regards,
Tomas Kukol

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Zinc-Seaside: Problem with POSTing UTF-8 JSON

Sven Van Caekenberghe-2
Hi Tomas,

Thanks for the report: this is an important area indeed.

However, the comment says it: this is intentional, and as far as I know, it is correct. You see, Zinc will correctly decode/encode any HTTP payload, using the supplied mime-type and/or charsets. Seaside is written such that it does not want this: it insists on doing this on its own. That is why ZnZincServerAdaptor is _not_ using the normal request reading code of Zn, but uses a special option to read everything binary. The stupid thing is that even though Seaside needs bytes, it wants them as a String. That is the reason for the otherwise brain dead #asString (and the implicit copy is inefficient as well).

Of course, you will see your special characters there if you do UTF8 decoding, but that is because you already know what is inside.

What normally happens, is that later on in the processing, Seaside will access the WARequest payload using proper decoding, using its own framework (much like what Zn would do). AFAIK this whole process works. You can actually test this using some of the functional tests.

I am not sure that Seaside-REST is doing the right thing (there were some issues with SmalltalkHub as well), but I would think so.

Are you sure you have set the correct encoding on the adaptor ?

Are you sure you are posting as application/json;charset=utf-8 and if you do not set the charset, are you sure utf-8 is the default ?

Are you sure your REST handler and/or JSON parser does the right thing ?

It is too late right now, but if we want to get further with this, I will need a failing unit test - if these exist in Seaside-REST, but I would assume so. I have no experience running Seaside-REST, I am using Zinc-REST myself, but I would like to learn.

Regards,

Sven

On 25 Jun 2013, at 23:24, Tomas Kukol <[hidden email]> wrote:

> Hi Sven.
>
> I've had a problem when POSTing non-ascii UTF-8 characters in JSON to Seaside REST service. I've located the problem in the method ZnZincServerAdaptor>>requestBodyFor: where the body of ZnRequest is translated to body of WARequest. I use Pharo 1.4 with Seaside 3.0.8 and Zinc-Seaside-SvenVanCaekenberghe.40.
>
> When the POSTed JSON contains non-ascii UTF-8 characters (Czech characters), they are corrupted. The problem is on the "MARKED" line, where the array of bytes changed to string by asString.
>
> "Problematic" code:
>
> ZnZincServerAdaptor>>requestBodyFor: aZincRequest
> ^ (aZincRequest method ~= #TRACE
> and: [ aZincRequest hasEntity
> and: [ aZincRequest entity isEmpty not
> and: [ (aZincRequest entity contentType matches: ZnMimeType applicationFormUrlEncoded) not
> and: [ (aZincRequest entity contentType matches: ZnMimeType multiPartFormData) not ] ] ] ])
> ifTrue: [
> "Seaside wants to do its own text conversions"
> aZincRequest entity bytes asString "MARKED" ]
> ifFalse: [
> String new ]
>
> I did a quick correction, which is not nice, but works for me:
>
> ZnZincServerAdaptor>>requestBodyFor: aZincRequest
> ^ (aZincRequest method ~= #TRACE
> and: [ aZincRequest hasEntity
> and: [ aZincRequest entity isEmpty not
> and: [ (aZincRequest entity contentType matches: ZnMimeType applicationFormUrlEncoded) not
> and: [ (aZincRequest entity contentType matches: ZnMimeType multiPartFormData) not ] ] ] ])
> ifTrue: [
> "Seaside wants to do its own text conversions"
> ZnUTF8Encoder new decodeBytes: aZincRequest entity bytes "CORRECTED" ]
> ifFalse: [
> String new ]
>
> My correction tries to decode byte array with ZnUTF8Encoder and the result is OK.
>
> Maybe I would recommend to use GRPharoUtf8Codec (although I like ZnUTF8Encoder more) or even better self codec (self = ZnZincServerAdaptor) to try to decode the bytes.
>
> Regards,
> Tomas Kukol
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside



--
Sven Van Caekenberghe
http://stfx.eu
Smalltalk is the Red Pill

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Zinc-Seaside: Problem with POSTing UTF-8 JSON

Tomas Kukol
Hi Sven,

you are right. Seaside needs it as a string. But I've found another problem with output (maybe because Seaside uses string???) which leads to error 'Improper store into indexable object'.

I have JSON on output. It is again string and there is this problem. In ZnZincServerAdaptor>>responseFrom: we are asking for contents.

ZnZincServerAdaptor>>responseFrom: aRequestContext
| partialHeaders cookies fullHeaders seasideResponse contents entity contentType |
seasideResponse := aRequestContext response.
partialHeaders := seasideResponse headers.
cookies := seasideResponse cookies.
fullHeaders := ZnHeaders defaultResponseHeaders.
partialHeaders keysAndValuesDo: [ :key :value |
fullHeaders at: key put: value ].
cookies do: [ :each |
fullHeaders at: 'Set-Cookie' add: each oldNetscapeString.
fullHeaders at: 'Set-Cookie2' add: each rfc2965String ].
contentType := seasideResponse contentType greaseString.
contents := seasideResponse contents. "<------------------------ HERE - we are asking for contents"
entity := (ZnEntity bytes: contents) contentType: contentType; yourself.
^ ZnResponse new
statusLine: (ZnStatusLine code: seasideResponse status);
headers: fullHeaders;
entity: entity;
yourself

It calls:

WABufferedResponse>>contents
^ contentsStream contents "<------------------------ HERE - normally, asking underlying stream for contents"

An the error is coming here:

RWBinaryOrTextStream>>contents
"Answer with a copy of my collection from 1 to readLimit."

| newArray |
isBinary ifFalse: [^ super contents]. "String"
readLimit := readLimit max: position.
newArray := ByteArray new: readLimit. "<------------------------ HERE - we are creating array of bytes (SmallInteger 0 - 255)"
^ newArray replaceFrom: 1
to: readLimit
with: collection  "<------------------------ HERE - but we are having WideString in collection - characters"
startingAt: 1.

Now we are calling primitive 105:

ByteArray>>replaceFrom: start to: stop with: replacement startingAt: repStart 
"Primitive. This destructively replaces elements from start to stop in the receiver starting at index, repStart, in the collection, replacement. Answer the receiver. Range checks are performed in the primitive only. Optional. See Object documentation whatIsAPrimitive."
<primitive: 105>
super replaceFrom: start to: stop with: replacement startingAt: repStart "<------------------------ HERE - it fails and continues here"

It calls loop in SequenceableCollection:

ByteArray(SequenceableCollection)>>replaceFrom: start to: stop with: replacement startingAt: repStart 
"This destructively replaces elements from start to stop in the receiver 
starting at index, repStart, in the sequenceable collection, 
replacementCollection. Answer the receiver. No range checks are 
performed."

| index repOff |
repOff := repStart - start.
index := start - 1.
[(index := index + 1) <= stop]
whileTrue: [self at: index put: (replacement at: repOff + index)] "<------------------------ HERE - here we are putting character into ByteArray"

Stops here at Object at primitive 61:

ByteArray(Object)>>at: index put: value 
"Primitive. Assumes receiver is indexable. Store the argument value in 
the indexable element of the receiver indicated by index. Fail if the 
index is not an Integer or is out of bounds. Or fail if the value is not of 
the right type for this kind of collection. Answer the value that was 
stored. Essential. See Object documentation whatIsAPrimitive."

<primitive: 61>
index isInteger ifTrue:
[self class isVariable
ifTrue: [(index >= 1 and: [index <= self size])
ifTrue: [self errorImproperStore] "<------------------------ HERE - ends here"
ifFalse: [self errorSubscriptBounds: index]]
ifFalse: [self errorNotIndexable]].
index isNumber
ifTrue: [^self at: index asInteger put: value]
ifFalse: [self errorNonIntegerIndex]

I've seen this problem mostly with Seaside-REST, but also in some other posts from Seaside.

Any idea how to fix it?

Regards,
Tomas


On Wed, Jun 26, 2013 at 12:17 AM, Sven Van Caekenberghe <[hidden email]> wrote:
Hi Tomas,

Thanks for the report: this is an important area indeed.

However, the comment says it: this is intentional, and as far as I know, it is correct. You see, Zinc will correctly decode/encode any HTTP payload, using the supplied mime-type and/or charsets. Seaside is written such that it does not want this: it insists on doing this on its own. That is why ZnZincServerAdaptor is _not_ using the normal request reading code of Zn, but uses a special option to read everything binary. The stupid thing is that even though Seaside needs bytes, it wants them as a String. That is the reason for the otherwise brain dead #asString (and the implicit copy is inefficient as well).

Of course, you will see your special characters there if you do UTF8 decoding, but that is because you already know what is inside.

What normally happens, is that later on in the processing, Seaside will access the WARequest payload using proper decoding, using its own framework (much like what Zn would do). AFAIK this whole process works. You can actually test this using some of the functional tests.

I am not sure that Seaside-REST is doing the right thing (there were some issues with SmalltalkHub as well), but I would think so.

Are you sure you have set the correct encoding on the adaptor ?

Are you sure you are posting as application/json;charset=utf-8 and if you do not set the charset, are you sure utf-8 is the default ?

Are you sure your REST handler and/or JSON parser does the right thing ?

It is too late right now, but if we want to get further with this, I will need a failing unit test - if these exist in Seaside-REST, but I would assume so. I have no experience running Seaside-REST, I am using Zinc-REST myself, but I would like to learn.

Regards,

Sven

On 25 Jun 2013, at 23:24, Tomas Kukol <[hidden email]> wrote:

> Hi Sven.
>
> I've had a problem when POSTing non-ascii UTF-8 characters in JSON to Seaside REST service. I've located the problem in the method ZnZincServerAdaptor>>requestBodyFor: where the body of ZnRequest is translated to body of WARequest. I use Pharo 1.4 with Seaside 3.0.8 and Zinc-Seaside-SvenVanCaekenberghe.40.
>
> When the POSTed JSON contains non-ascii UTF-8 characters (Czech characters), they are corrupted. The problem is on the "MARKED" line, where the array of bytes changed to string by asString.
>
> "Problematic" code:
>
> ZnZincServerAdaptor>>requestBodyFor: aZincRequest
>       ^ (aZincRequest method ~= #TRACE
>               and: [ aZincRequest hasEntity
>                       and: [ aZincRequest entity isEmpty not
>                               and: [ (aZincRequest entity contentType matches: ZnMimeType applicationFormUrlEncoded) not
>                                       and: [ (aZincRequest entity contentType matches: ZnMimeType multiPartFormData) not ] ] ] ])
>                       ifTrue: [
>                               "Seaside wants to do its own text conversions"
>                               aZincRequest entity bytes asString "MARKED" ]
>                       ifFalse: [
>                               String new ]
>
> I did a quick correction, which is not nice, but works for me:
>
> ZnZincServerAdaptor>>requestBodyFor: aZincRequest
>       ^ (aZincRequest method ~= #TRACE
>               and: [ aZincRequest hasEntity
>                       and: [ aZincRequest entity isEmpty not
>                               and: [ (aZincRequest entity contentType matches: ZnMimeType applicationFormUrlEncoded) not
>                                       and: [ (aZincRequest entity contentType matches: ZnMimeType multiPartFormData) not ] ] ] ])
>                       ifTrue: [
>                               "Seaside wants to do its own text conversions"
>                               ZnUTF8Encoder new decodeBytes: aZincRequest entity bytes "CORRECTED" ]
>                       ifFalse: [
>                               String new ]
>
> My correction tries to decode byte array with ZnUTF8Encoder and the result is OK.
>
> Maybe I would recommend to use GRPharoUtf8Codec (although I like ZnUTF8Encoder more) or even better self codec (self = ZnZincServerAdaptor) to try to decode the bytes.
>
> Regards,
> Tomas Kukol
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside



--
Sven Van Caekenberghe
http://stfx.eu
Smalltalk is the Red Pill

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside


_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Zinc-Seaside: Problem with POSTing UTF-8 JSON

Sven Van Caekenberghe-2
Hi Tomas,

On 26 Jun 2013, at 13:20, Tomas Kukol <[hidden email]> wrote:

> Hi Sven,
>
> you are right. Seaside needs it as a string. But I've found another problem with output (maybe because Seaside uses string???) which leads to error 'Improper store into indexable object'.
>
> I have JSON on output. It is again string and there is this problem. In ZnZincServerAdaptor>>responseFrom: we are asking for contents.

I don't know much about Seaside-REST but I would guess, from my general understanding how Seaside works, that if you generate output, like JSON, your output has to pass through an encoder before it is stored as bytes (well actually a ByteString, but that is another story) inside RWBinaryOrTextStream's contents of the WABufferedResponse. The encoder will make sure WideCharacters get encoded properly and then the #replaceFrom:to:with:startingAt: will work (and magically bridge the ByteArray/ByteString gap).

So my guess is that you either have not set the proper encoder on the response when writing output to it, or you write the output the wrong way.

There has to be a codec stream in between. See

WAServerAdaptor>>#responseFor:
GRPharoUtf8Codec>>#encoderFor:

HTH,

Sven

> ZnZincServerAdaptor>>responseFrom: aRequestContext
> | partialHeaders cookies fullHeaders seasideResponse contents entity contentType |
> seasideResponse := aRequestContext response.
> partialHeaders := seasideResponse headers.
> cookies := seasideResponse cookies.
> fullHeaders := ZnHeaders defaultResponseHeaders.
> partialHeaders keysAndValuesDo: [ :key :value |
> fullHeaders at: key put: value ].
> cookies do: [ :each |
> fullHeaders at: 'Set-Cookie' add: each oldNetscapeString.
> fullHeaders at: 'Set-Cookie2' add: each rfc2965String ].
> contentType := seasideResponse contentType greaseString.
> contents := seasideResponse contents. "<------------------------ HERE - we are asking for contents"
> entity := (ZnEntity bytes: contents) contentType: contentType; yourself.
> ^ ZnResponse new
> statusLine: (ZnStatusLine code: seasideResponse status);
> headers: fullHeaders;
> entity: entity;
> yourself
>
> It calls:
>
> WABufferedResponse>>contents
> ^ contentsStream contents "<------------------------ HERE - normally, asking underlying stream for contents"
>
> An the error is coming here:
>
> RWBinaryOrTextStream>>contents
> "Answer with a copy of my collection from 1 to readLimit."
>
> | newArray |
> isBinary ifFalse: [^ super contents]. "String"
> readLimit := readLimit max: position.
> newArray := ByteArray new: readLimit. "<------------------------ HERE - we are creating array of bytes (SmallInteger 0 - 255)"
> ^ newArray replaceFrom: 1
> to: readLimit
> with: collection  "<------------------------ HERE - but we are having WideString in collection - characters"
> startingAt: 1.
>
> Now we are calling primitive 105:
>
> ByteArray>>replaceFrom: start to: stop with: replacement startingAt: repStart
> "Primitive. This destructively replaces elements from start to stop in the receiver starting at index, repStart, in the collection, replacement. Answer the receiver. Range checks are performed in the primitive only. Optional. See Object documentation whatIsAPrimitive."
> <primitive: 105>
> super replaceFrom: start to: stop with: replacement startingAt: repStart "<------------------------ HERE - it fails and continues here"
>
> It calls loop in SequenceableCollection:
>
> ByteArray(SequenceableCollection)>>replaceFrom: start to: stop with: replacement startingAt: repStart
> "This destructively replaces elements from start to stop in the receiver
> starting at index, repStart, in the sequenceable collection,
> replacementCollection. Answer the receiver. No range checks are
> performed."
>
> | index repOff |
> repOff := repStart - start.
> index := start - 1.
> [(index := index + 1) <= stop]
> whileTrue: [self at: index put: (replacement at: repOff + index)] "<------------------------ HERE - here we are putting character into ByteArray"
>
> Stops here at Object at primitive 61:
>
> ByteArray(Object)>>at: index put: value
> "Primitive. Assumes receiver is indexable. Store the argument value in
> the indexable element of the receiver indicated by index. Fail if the
> index is not an Integer or is out of bounds. Or fail if the value is not of
> the right type for this kind of collection. Answer the value that was
> stored. Essential. See Object documentation whatIsAPrimitive."
>
> <primitive: 61>
> index isInteger ifTrue:
> [self class isVariable
> ifTrue: [(index >= 1 and: [index <= self size])
> ifTrue: [self errorImproperStore] "<------------------------ HERE - ends here"
> ifFalse: [self errorSubscriptBounds: index]]
> ifFalse: [self errorNotIndexable]].
> index isNumber
> ifTrue: [^self at: index asInteger put: value]
> ifFalse: [self errorNonIntegerIndex]
>
> I've seen this problem mostly with Seaside-REST, but also in some other posts from Seaside.
>
> Any idea how to fix it?
>
> Regards,
> Tomas
>
>
> On Wed, Jun 26, 2013 at 12:17 AM, Sven Van Caekenberghe <[hidden email]> wrote:
> Hi Tomas,
>
> Thanks for the report: this is an important area indeed.
>
> However, the comment says it: this is intentional, and as far as I know, it is correct. You see, Zinc will correctly decode/encode any HTTP payload, using the supplied mime-type and/or charsets. Seaside is written such that it does not want this: it insists on doing this on its own. That is why ZnZincServerAdaptor is _not_ using the normal request reading code of Zn, but uses a special option to read everything binary. The stupid thing is that even though Seaside needs bytes, it wants them as a String. That is the reason for the otherwise brain dead #asString (and the implicit copy is inefficient as well).
>
> Of course, you will see your special characters there if you do UTF8 decoding, but that is because you already know what is inside.
>
> What normally happens, is that later on in the processing, Seaside will access the WARequest payload using proper decoding, using its own framework (much like what Zn would do). AFAIK this whole process works. You can actually test this using some of the functional tests.
>
> I am not sure that Seaside-REST is doing the right thing (there were some issues with SmalltalkHub as well), but I would think so.
>
> Are you sure you have set the correct encoding on the adaptor ?
>
> Are you sure you are posting as application/json;charset=utf-8 and if you do not set the charset, are you sure utf-8 is the default ?
>
> Are you sure your REST handler and/or JSON parser does the right thing ?
>
> It is too late right now, but if we want to get further with this, I will need a failing unit test - if these exist in Seaside-REST, but I would assume so. I have no experience running Seaside-REST, I am using Zinc-REST myself, but I would like to learn.
>
> Regards,
>
> Sven
>
> On 25 Jun 2013, at 23:24, Tomas Kukol <[hidden email]> wrote:
>
> > Hi Sven.
> >
> > I've had a problem when POSTing non-ascii UTF-8 characters in JSON to Seaside REST service. I've located the problem in the method ZnZincServerAdaptor>>requestBodyFor: where the body of ZnRequest is translated to body of WARequest. I use Pharo 1.4 with Seaside 3.0.8 and Zinc-Seaside-SvenVanCaekenberghe.40.
> >
> > When the POSTed JSON contains non-ascii UTF-8 characters (Czech characters), they are corrupted. The problem is on the "MARKED" line, where the array of bytes changed to string by asString.
> >
> > "Problematic" code:
> >
> > ZnZincServerAdaptor>>requestBodyFor: aZincRequest
> >       ^ (aZincRequest method ~= #TRACE
> >               and: [ aZincRequest hasEntity
> >                       and: [ aZincRequest entity isEmpty not
> >                               and: [ (aZincRequest entity contentType matches: ZnMimeType applicationFormUrlEncoded) not
> >                                       and: [ (aZincRequest entity contentType matches: ZnMimeType multiPartFormData) not ] ] ] ])
> >                       ifTrue: [
> >                               "Seaside wants to do its own text conversions"
> >                               aZincRequest entity bytes asString "MARKED" ]
> >                       ifFalse: [
> >                               String new ]
> >
> > I did a quick correction, which is not nice, but works for me:
> >
> > ZnZincServerAdaptor>>requestBodyFor: aZincRequest
> >       ^ (aZincRequest method ~= #TRACE
> >               and: [ aZincRequest hasEntity
> >                       and: [ aZincRequest entity isEmpty not
> >                               and: [ (aZincRequest entity contentType matches: ZnMimeType applicationFormUrlEncoded) not
> >                                       and: [ (aZincRequest entity contentType matches: ZnMimeType multiPartFormData) not ] ] ] ])
> >                       ifTrue: [
> >                               "Seaside wants to do its own text conversions"
> >                               ZnUTF8Encoder new decodeBytes: aZincRequest entity bytes "CORRECTED" ]
> >                       ifFalse: [
> >                               String new ]
> >
> > My correction tries to decode byte array with ZnUTF8Encoder and the result is OK.
> >
> > Maybe I would recommend to use GRPharoUtf8Codec (although I like ZnUTF8Encoder more) or even better self codec (self = ZnZincServerAdaptor) to try to decode the bytes.
> >
> > Regards,
> > Tomas Kukol
> > _______________________________________________
> > seaside mailing list
> > [hidden email]
> > http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>
>
>
> --
> Sven Van Caekenberghe
> http://stfx.eu
> Smalltalk is the Red Pill
>
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Zinc-Seaside: Problem with POSTing UTF-8 JSON

Tomas Kukol
Hi Sven,

thanks for the answers. My REST services are really simple, for example there is a list of users:

GPRestfulHandler>>getUsers

<get>
<path: 'user/list'>
<produces: 'application/json; charset=utf-8'>
| instance container items |
instance := GPUser new.
container := instance descriptionId , instance descriptionLogin.
items := self database getUsers.
^ (items collect: [ :item | item asDictionaryFrom: container ]) asJson

There is a JSON result:

[{"Id":"688a7ymp9zn60qczvvyniprwq","Login":"tomas"},{"Id":"av0t1s9u4ddu747hd2xyfi58","Login":"petr"}]
Detail of user can be read by this method:

GPRestfulHandler>>getUserByLogin: aLogin

<get>
<path: 'user/detail/by-login/{aLogin}'>
<produces: 'application/json; charset=utf-8'>
| user |
user := self database getUserByLogin: aLogin.
user isNil
ifFalse: [ ^ user asJson ]
ifTrue: [ self respondAsUserWasNotFindByLogin: aLogin ]

Result is here. I had to fix the failing ByteArray method to get GoalName with Czech characters:
{"Id":"688a7ymp9zn60qczvvyniprwq","Login":"tomas","CurrentAccountBalance":12000,"SavingsAccountReserve":0,"SavingsAccountHeap":0,"InterestRate":1,"PaymentDay":15,"SimulationDate":"29 May 2013","SavingsAccountInterestReserve":0,"SavingsAccountInterestHeap":0,"Goals":[{"GoalName":"ěščřžýáíé-ĚŠČŘŽÝÁÍÉ","GoalAmount":8000,"MaturityDate":"29 November 2013"}],"Plans":[{"PaymentDate":"29 May 2013","PaymentAmount":1140.410292918764},{"PaymentDate":"29 June 2013","PaymentAmount":1140.410292918764},{"PaymentDate":"29 July 2013","PaymentAmount":1140.410292918764},{"PaymentDate":"29 August 2013","PaymentAmount":1140.410292918764},{"PaymentDate":"29 September 2013","PaymentAmount":1140.410292918764},{"PaymentDate":"29 October 2013","PaymentAmount":1140.410292918764},{"PaymentDate":"29 November 2013","PaymentAmount":1140.410292918764}]}

Can you see any problem with the REST method?

Tomas



On Wed, Jun 26, 2013 at 2:00 PM, Sven Van Caekenberghe <[hidden email]> wrote:
Hi Tomas,

On 26 Jun 2013, at 13:20, Tomas Kukol <[hidden email]> wrote:

> Hi Sven,
>
> you are right. Seaside needs it as a string. But I've found another problem with output (maybe because Seaside uses string???) which leads to error 'Improper store into indexable object'.
>
> I have JSON on output. It is again string and there is this problem. In ZnZincServerAdaptor>>responseFrom: we are asking for contents.

I don't know much about Seaside-REST but I would guess, from my general understanding how Seaside works, that if you generate output, like JSON, your output has to pass through an encoder before it is stored as bytes (well actually a ByteString, but that is another story) inside RWBinaryOrTextStream's contents of the WABufferedResponse. The encoder will make sure WideCharacters get encoded properly and then the #replaceFrom:to:with:startingAt: will work (and magically bridge the ByteArray/ByteString gap).

So my guess is that you either have not set the proper encoder on the response when writing output to it, or you write the output the wrong way.

There has to be a codec stream in between. See

WAServerAdaptor>>#responseFor:
GRPharoUtf8Codec>>#encoderFor:

HTH,

Sven

> ZnZincServerAdaptor>>responseFrom: aRequestContext
>       | partialHeaders cookies fullHeaders seasideResponse contents entity contentType |
>       seasideResponse := aRequestContext response.
>       partialHeaders := seasideResponse headers.
>       cookies := seasideResponse cookies.
>       fullHeaders := ZnHeaders defaultResponseHeaders.
>       partialHeaders keysAndValuesDo: [ :key :value |
>               fullHeaders at: key put: value ].
>       cookies do: [ :each |
>               fullHeaders at: 'Set-Cookie' add: each oldNetscapeString.
>               fullHeaders at: 'Set-Cookie2' add: each rfc2965String ].
>       contentType := seasideResponse contentType greaseString.
>       contents := seasideResponse contents. "<------------------------ HERE - we are asking for contents"
>       entity := (ZnEntity bytes: contents) contentType: contentType; yourself.
>       ^ ZnResponse new
>               statusLine: (ZnStatusLine code: seasideResponse status);
>               headers: fullHeaders;
>               entity: entity;
>               yourself
>
> It calls:
>
> WABufferedResponse>>contents
>       ^ contentsStream contents "<------------------------ HERE - normally, asking underlying stream for contents"
>
> An the error is coming here:
>
> RWBinaryOrTextStream>>contents
>       "Answer with a copy of my collection from 1 to readLimit."
>
>       | newArray |
>       isBinary ifFalse: [^ super contents].   "String"
>       readLimit := readLimit max: position.
>       newArray := ByteArray new: readLimit. "<------------------------ HERE - we are creating array of bytes (SmallInteger 0 - 255)"
>       ^ newArray replaceFrom: 1
>               to: readLimit
>               with: collection  "<------------------------ HERE - but we are having WideString in collection - characters"
>               startingAt: 1.
>
> Now we are calling primitive 105:
>
> ByteArray>>replaceFrom: start to: stop with: replacement startingAt: repStart
>       "Primitive. This destructively replaces elements from start to stop in the receiver starting at index, repStart, in the collection, replacement. Answer the receiver. Range checks are performed in the primitive only. Optional. See Object documentation whatIsAPrimitive."
>       <primitive: 105>
>       super replaceFrom: start to: stop with: replacement startingAt: repStart "<------------------------ HERE - it fails and continues here"
>
> It calls loop in SequenceableCollection:
>
> ByteArray(SequenceableCollection)>>replaceFrom: start to: stop with: replacement startingAt: repStart
>       "This destructively replaces elements from start to stop in the receiver
>       starting at index, repStart, in the sequenceable collection,
>       replacementCollection. Answer the receiver. No range checks are
>       performed."
>
>       | index repOff |
>       repOff := repStart - start.
>       index := start - 1.
>       [(index := index + 1) <= stop]
>               whileTrue: [self at: index put: (replacement at: repOff + index)] "<------------------------ HERE - here we are putting character into ByteArray"
>
> Stops here at Object at primitive 61:
>
> ByteArray(Object)>>at: index put: value
>       "Primitive. Assumes receiver is indexable. Store the argument value in
>       the indexable element of the receiver indicated by index. Fail if the
>       index is not an Integer or is out of bounds. Or fail if the value is not of
>       the right type for this kind of collection. Answer the value that was
>       stored. Essential. See Object documentation whatIsAPrimitive."
>
>       <primitive: 61>
>       index isInteger ifTrue:
>               [self class isVariable
>                       ifTrue: [(index >= 1 and: [index <= self size])
>                                       ifTrue: [self errorImproperStore] "<------------------------ HERE - ends here"
>                                       ifFalse: [self errorSubscriptBounds: index]]
>                       ifFalse: [self errorNotIndexable]].
>       index isNumber
>               ifTrue: [^self at: index asInteger put: value]
>               ifFalse: [self errorNonIntegerIndex]
>
> I've seen this problem mostly with Seaside-REST, but also in some other posts from Seaside.
>
> Any idea how to fix it?
>
> Regards,
> Tomas
>
>
> On Wed, Jun 26, 2013 at 12:17 AM, Sven Van Caekenberghe <[hidden email]> wrote:
> Hi Tomas,
>
> Thanks for the report: this is an important area indeed.
>
> However, the comment says it: this is intentional, and as far as I know, it is correct. You see, Zinc will correctly decode/encode any HTTP payload, using the supplied mime-type and/or charsets. Seaside is written such that it does not want this: it insists on doing this on its own. That is why ZnZincServerAdaptor is _not_ using the normal request reading code of Zn, but uses a special option to read everything binary. The stupid thing is that even though Seaside needs bytes, it wants them as a String. That is the reason for the otherwise brain dead #asString (and the implicit copy is inefficient as well).
>
> Of course, you will see your special characters there if you do UTF8 decoding, but that is because you already know what is inside.
>
> What normally happens, is that later on in the processing, Seaside will access the WARequest payload using proper decoding, using its own framework (much like what Zn would do). AFAIK this whole process works. You can actually test this using some of the functional tests.
>
> I am not sure that Seaside-REST is doing the right thing (there were some issues with SmalltalkHub as well), but I would think so.
>
> Are you sure you have set the correct encoding on the adaptor ?
>
> Are you sure you are posting as application/json;charset=utf-8 and if you do not set the charset, are you sure utf-8 is the default ?
>
> Are you sure your REST handler and/or JSON parser does the right thing ?
>
> It is too late right now, but if we want to get further with this, I will need a failing unit test - if these exist in Seaside-REST, but I would assume so. I have no experience running Seaside-REST, I am using Zinc-REST myself, but I would like to learn.
>
> Regards,
>
> Sven
>
> On 25 Jun 2013, at 23:24, Tomas Kukol <[hidden email]> wrote:
>
> > Hi Sven.
> >
> > I've had a problem when POSTing non-ascii UTF-8 characters in JSON to Seaside REST service. I've located the problem in the method ZnZincServerAdaptor>>requestBodyFor: where the body of ZnRequest is translated to body of WARequest. I use Pharo 1.4 with Seaside 3.0.8 and Zinc-Seaside-SvenVanCaekenberghe.40.
> >
> > When the POSTed JSON contains non-ascii UTF-8 characters (Czech characters), they are corrupted. The problem is on the "MARKED" line, where the array of bytes changed to string by asString.
> >
> > "Problematic" code:
> >
> > ZnZincServerAdaptor>>requestBodyFor: aZincRequest
> >       ^ (aZincRequest method ~= #TRACE
> >               and: [ aZincRequest hasEntity
> >                       and: [ aZincRequest entity isEmpty not
> >                               and: [ (aZincRequest entity contentType matches: ZnMimeType applicationFormUrlEncoded) not
> >                                       and: [ (aZincRequest entity contentType matches: ZnMimeType multiPartFormData) not ] ] ] ])
> >                       ifTrue: [
> >                               "Seaside wants to do its own text conversions"
> >                               aZincRequest entity bytes asString "MARKED" ]
> >                       ifFalse: [
> >                               String new ]
> >
> > I did a quick correction, which is not nice, but works for me:
> >
> > ZnZincServerAdaptor>>requestBodyFor: aZincRequest
> >       ^ (aZincRequest method ~= #TRACE
> >               and: [ aZincRequest hasEntity
> >                       and: [ aZincRequest entity isEmpty not
> >                               and: [ (aZincRequest entity contentType matches: ZnMimeType applicationFormUrlEncoded) not
> >                                       and: [ (aZincRequest entity contentType matches: ZnMimeType multiPartFormData) not ] ] ] ])
> >                       ifTrue: [
> >                               "Seaside wants to do its own text conversions"
> >                               ZnUTF8Encoder new decodeBytes: aZincRequest entity bytes "CORRECTED" ]
> >                       ifFalse: [
> >                               String new ]
> >
> > My correction tries to decode byte array with ZnUTF8Encoder and the result is OK.
> >
> > Maybe I would recommend to use GRPharoUtf8Codec (although I like ZnUTF8Encoder more) or even better self codec (self = ZnZincServerAdaptor) to try to decode the bytes.
> >
> > Regards,
> > Tomas Kukol
> > _______________________________________________
> > seaside mailing list
> > [hidden email]
> > http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>
>
>
> --
> Sven Van Caekenberghe
> http://stfx.eu
> Smalltalk is the Red Pill
>
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside


_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Zinc-Seaside: Problem with POSTing UTF-8 JSON

Philippe Marschall
In reply to this post by Sven Van Caekenberghe-2
On Wed, Jun 26, 2013 at 12:17 AM, Sven Van Caekenberghe <[hidden email]> wrote:

> Hi Tomas,
>
> Thanks for the report: this is an important area indeed.
>
> However, the comment says it: this is intentional, and as far as I know, it is correct. You see, Zinc will correctly decode/encode any HTTP payload, using the supplied mime-type and/or charsets. Seaside is written such that it does not want this: it insists on doing this on its own. That is why ZnZincServerAdaptor is _not_ using the normal request reading code of Zn, but uses a special option to read everything binary. The stupid thing is that even though Seaside needs bytes, it wants them as a String. That is the reason for the otherwise brain dead #asString (and the implicit copy is inefficient as well).
>
> Of course, you will see your special characters there if you do UTF8 decoding, but that is because you already know what is inside.
>
> What normally happens, is that later on in the processing, Seaside will access the WARequest payload using proper decoding, using its own framework (much like what Zn would do). AFAIK this whole process works. You can actually test this using some of the functional tests.
>
> I am not sure that Seaside-REST is doing the right thing (there were some issues with SmalltalkHub as well), but I would think so.
>
> Are you sure you have set the correct encoding on the adaptor ?
>
> Are you sure you are posting as application/json;charset=utf-8 and if you do not set the charset, are you sure utf-8 is the default ?
>
> Are you sure your REST handler and/or JSON parser does the right thing ?
>
> It is too late right now, but if we want to get further with this, I will need a failing unit test - if these exist in Seaside-REST, but I would assume so. I have no experience running Seaside-REST, I am using Zinc-REST myself, but I would like to learn.

You're right. Seaside-REST doesn't touch the request body. Thomas, can
you check whether you send somewhere #rawBody? If so replace it with
#bodyDecodeUsing:. You can find out encoding from the content type so
it should look something like this:

request bodyDecodeUsing: request contentType charSet

Cheers
Philippe
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Zinc-Seaside: Problem with POSTing UTF-8 JSON

Sven Van Caekenberghe-2
In reply to this post by Tomas Kukol
Tomas,

I am not sure what one is supposed to return from #getUsers.

Naively, I would guess just a [Wide]String with the <produces: 'application/json; charset=utf-8'> telling the Seaside-REST framework to do the right thing, but I just don't know.

In Zinc-REST you would do something like:

GPGetUsersRestCall>>#get
        json := NeoJSONWriter toString: { #name->'čeština' } asDictionary.
        self response: (ZnResponse ok: (ZnEntity with: json type: ZnMimeType applicationJson setCharSetUTF8))

and it would work. If all your REST calls work with JSON, this could become, by using a little helper method:

GPGetUsersRestCall>>#get
        self jsonResponse: { #name->'čeština' } asDictionary

Regards,

Sven

On 26 Jun 2013, at 15:35, Tomas Kukol <[hidden email]> wrote:

> Hi Sven,
>
> thanks for the answers. My REST services are really simple, for example there is a list of users:
>
> GPRestfulHandler>>getUsers
>
> <get>
> <path: 'user/list'>
> <produces: 'application/json; charset=utf-8'>
> | instance container items |
> instance := GPUser new.
> container := instance descriptionId , instance descriptionLogin.
> items := self database getUsers.
> ^ (items collect: [ :item | item asDictionaryFrom: container ]) asJson
>
> There is a JSON result:
>
> [{"Id":"688a7ymp9zn60qczvvyniprwq","Login":"tomas"},{"Id":"av0t1s9u4ddu747hd2xyfi58","Login":"petr"}]
> Detail of user can be read by this method:
>
> GPRestfulHandler>>getUserByLogin: aLogin
>
> <get>
> <path: 'user/detail/by-login/{aLogin}'>
> <produces: 'application/json; charset=utf-8'>
> | user |
> user := self database getUserByLogin: aLogin.
> user isNil
> ifFalse: [ ^ user asJson ]
> ifTrue: [ self respondAsUserWasNotFindByLogin: aLogin ]
>
> Result is here. I had to fix the failing ByteArray method to get GoalName with Czech characters:
> {"Id":"688a7ymp9zn60qczvvyniprwq","Login":"tomas","CurrentAccountBalance":12000,"SavingsAccountReserve":0,"SavingsAccountHeap":0,"InterestRate":1,"PaymentDay":15,"SimulationDate":"29 May 2013","SavingsAccountInterestReserve":0,"SavingsAccountInterestHeap":0,"Goals":[{"GoalName":"ěščřžýáíé-ĚŠČŘŽÝÁÍÉ","GoalAmount":8000,"MaturityDate":"29 November 2013"}],"Plans":[{"PaymentDate":"29 May 2013","PaymentAmount":1140.410292918764},{"PaymentDate":"29 June 2013","PaymentAmount":1140.410292918764},{"PaymentDate":"29 July 2013","PaymentAmount":1140.410292918764},{"PaymentDate":"29 August 2013","PaymentAmount":1140.410292918764},{"PaymentDate":"29 September 2013","PaymentAmount":1140.410292918764},{"PaymentDate":"29 October 2013","PaymentAmount":1140.410292918764},{"PaymentDate":"29 November 2013","PaymentAmount":1140.410292918764}]}
>
>
> Can you see any problem with the REST method?
>
> Tomas
>
>
>
> On Wed, Jun 26, 2013 at 2:00 PM, Sven Van Caekenberghe <[hidden email]> wrote:
> Hi Tomas,
>
> On 26 Jun 2013, at 13:20, Tomas Kukol <[hidden email]> wrote:
>
> > Hi Sven,
> >
> > you are right. Seaside needs it as a string. But I've found another problem with output (maybe because Seaside uses string???) which leads to error 'Improper store into indexable object'.
> >
> > I have JSON on output. It is again string and there is this problem. In ZnZincServerAdaptor>>responseFrom: we are asking for contents.
>
> I don't know much about Seaside-REST but I would guess, from my general understanding how Seaside works, that if you generate output, like JSON, your output has to pass through an encoder before it is stored as bytes (well actually a ByteString, but that is another story) inside RWBinaryOrTextStream's contents of the WABufferedResponse. The encoder will make sure WideCharacters get encoded properly and then the #replaceFrom:to:with:startingAt: will work (and magically bridge the ByteArray/ByteString gap).
>
> So my guess is that you either have not set the proper encoder on the response when writing output to it, or you write the output the wrong way.
>
> There has to be a codec stream in between. See
>
> WAServerAdaptor>>#responseFor:
> GRPharoUtf8Codec>>#encoderFor:
>
> HTH,
>
> Sven
>
> > ZnZincServerAdaptor>>responseFrom: aRequestContext
> >       | partialHeaders cookies fullHeaders seasideResponse contents entity contentType |
> >       seasideResponse := aRequestContext response.
> >       partialHeaders := seasideResponse headers.
> >       cookies := seasideResponse cookies.
> >       fullHeaders := ZnHeaders defaultResponseHeaders.
> >       partialHeaders keysAndValuesDo: [ :key :value |
> >               fullHeaders at: key put: value ].
> >       cookies do: [ :each |
> >               fullHeaders at: 'Set-Cookie' add: each oldNetscapeString.
> >               fullHeaders at: 'Set-Cookie2' add: each rfc2965String ].
> >       contentType := seasideResponse contentType greaseString.
> >       contents := seasideResponse contents. "<------------------------ HERE - we are asking for contents"
> >       entity := (ZnEntity bytes: contents) contentType: contentType; yourself.
> >       ^ ZnResponse new
> >               statusLine: (ZnStatusLine code: seasideResponse status);
> >               headers: fullHeaders;
> >               entity: entity;
> >               yourself
> >
> > It calls:
> >
> > WABufferedResponse>>contents
> >       ^ contentsStream contents "<------------------------ HERE - normally, asking underlying stream for contents"
> >
> > An the error is coming here:
> >
> > RWBinaryOrTextStream>>contents
> >       "Answer with a copy of my collection from 1 to readLimit."
> >
> >       | newArray |
> >       isBinary ifFalse: [^ super contents].   "String"
> >       readLimit := readLimit max: position.
> >       newArray := ByteArray new: readLimit. "<------------------------ HERE - we are creating array of bytes (SmallInteger 0 - 255)"
> >       ^ newArray replaceFrom: 1
> >               to: readLimit
> >               with: collection  "<------------------------ HERE - but we are having WideString in collection - characters"
> >               startingAt: 1.
> >
> > Now we are calling primitive 105:
> >
> > ByteArray>>replaceFrom: start to: stop with: replacement startingAt: repStart
> >       "Primitive. This destructively replaces elements from start to stop in the receiver starting at index, repStart, in the collection, replacement. Answer the receiver. Range checks are performed in the primitive only. Optional. See Object documentation whatIsAPrimitive."
> >       <primitive: 105>
> >       super replaceFrom: start to: stop with: replacement startingAt: repStart "<------------------------ HERE - it fails and continues here"
> >
> > It calls loop in SequenceableCollection:
> >
> > ByteArray(SequenceableCollection)>>replaceFrom: start to: stop with: replacement startingAt: repStart
> >       "This destructively replaces elements from start to stop in the receiver
> >       starting at index, repStart, in the sequenceable collection,
> >       replacementCollection. Answer the receiver. No range checks are
> >       performed."
> >
> >       | index repOff |
> >       repOff := repStart - start.
> >       index := start - 1.
> >       [(index := index + 1) <= stop]
> >               whileTrue: [self at: index put: (replacement at: repOff + index)] "<------------------------ HERE - here we are putting character into ByteArray"
> >
> > Stops here at Object at primitive 61:
> >
> > ByteArray(Object)>>at: index put: value
> >       "Primitive. Assumes receiver is indexable. Store the argument value in
> >       the indexable element of the receiver indicated by index. Fail if the
> >       index is not an Integer or is out of bounds. Or fail if the value is not of
> >       the right type for this kind of collection. Answer the value that was
> >       stored. Essential. See Object documentation whatIsAPrimitive."
> >
> >       <primitive: 61>
> >       index isInteger ifTrue:
> >               [self class isVariable
> >                       ifTrue: [(index >= 1 and: [index <= self size])
> >                                       ifTrue: [self errorImproperStore] "<------------------------ HERE - ends here"
> >                                       ifFalse: [self errorSubscriptBounds: index]]
> >                       ifFalse: [self errorNotIndexable]].
> >       index isNumber
> >               ifTrue: [^self at: index asInteger put: value]
> >               ifFalse: [self errorNonIntegerIndex]
> >
> > I've seen this problem mostly with Seaside-REST, but also in some other posts from Seaside.
> >
> > Any idea how to fix it?
> >
> > Regards,
> > Tomas
> >
> >
> > On Wed, Jun 26, 2013 at 12:17 AM, Sven Van Caekenberghe <[hidden email]> wrote:
> > Hi Tomas,
> >
> > Thanks for the report: this is an important area indeed.
> >
> > However, the comment says it: this is intentional, and as far as I know, it is correct. You see, Zinc will correctly decode/encode any HTTP payload, using the supplied mime-type and/or charsets. Seaside is written such that it does not want this: it insists on doing this on its own. That is why ZnZincServerAdaptor is _not_ using the normal request reading code of Zn, but uses a special option to read everything binary. The stupid thing is that even though Seaside needs bytes, it wants them as a String. That is the reason for the otherwise brain dead #asString (and the implicit copy is inefficient as well).
> >
> > Of course, you will see your special characters there if you do UTF8 decoding, but that is because you already know what is inside.
> >
> > What normally happens, is that later on in the processing, Seaside will access the WARequest payload using proper decoding, using its own framework (much like what Zn would do). AFAIK this whole process works. You can actually test this using some of the functional tests.
> >
> > I am not sure that Seaside-REST is doing the right thing (there were some issues with SmalltalkHub as well), but I would think so.
> >
> > Are you sure you have set the correct encoding on the adaptor ?
> >
> > Are you sure you are posting as application/json;charset=utf-8 and if you do not set the charset, are you sure utf-8 is the default ?
> >
> > Are you sure your REST handler and/or JSON parser does the right thing ?
> >
> > It is too late right now, but if we want to get further with this, I will need a failing unit test - if these exist in Seaside-REST, but I would assume so. I have no experience running Seaside-REST, I am using Zinc-REST myself, but I would like to learn.
> >
> > Regards,
> >
> > Sven
> >
> > On 25 Jun 2013, at 23:24, Tomas Kukol <[hidden email]> wrote:
> >
> > > Hi Sven.
> > >
> > > I've had a problem when POSTing non-ascii UTF-8 characters in JSON to Seaside REST service. I've located the problem in the method ZnZincServerAdaptor>>requestBodyFor: where the body of ZnRequest is translated to body of WARequest. I use Pharo 1.4 with Seaside 3.0.8 and Zinc-Seaside-SvenVanCaekenberghe.40.
> > >
> > > When the POSTed JSON contains non-ascii UTF-8 characters (Czech characters), they are corrupted. The problem is on the "MARKED" line, where the array of bytes changed to string by asString.
> > >
> > > "Problematic" code:
> > >
> > > ZnZincServerAdaptor>>requestBodyFor: aZincRequest
> > >       ^ (aZincRequest method ~= #TRACE
> > >               and: [ aZincRequest hasEntity
> > >                       and: [ aZincRequest entity isEmpty not
> > >                               and: [ (aZincRequest entity contentType matches: ZnMimeType applicationFormUrlEncoded) not
> > >                                       and: [ (aZincRequest entity contentType matches: ZnMimeType multiPartFormData) not ] ] ] ])
> > >                       ifTrue: [
> > >                               "Seaside wants to do its own text conversions"
> > >                               aZincRequest entity bytes asString "MARKED" ]
> > >                       ifFalse: [
> > >                               String new ]
> > >
> > > I did a quick correction, which is not nice, but works for me:
> > >
> > > ZnZincServerAdaptor>>requestBodyFor: aZincRequest
> > >       ^ (aZincRequest method ~= #TRACE
> > >               and: [ aZincRequest hasEntity
> > >                       and: [ aZincRequest entity isEmpty not
> > >                               and: [ (aZincRequest entity contentType matches: ZnMimeType applicationFormUrlEncoded) not
> > >                                       and: [ (aZincRequest entity contentType matches: ZnMimeType multiPartFormData) not ] ] ] ])
> > >                       ifTrue: [
> > >                               "Seaside wants to do its own text conversions"
> > >                               ZnUTF8Encoder new decodeBytes: aZincRequest entity bytes "CORRECTED" ]
> > >                       ifFalse: [
> > >                               String new ]
> > >
> > > My correction tries to decode byte array with ZnUTF8Encoder and the result is OK.
> > >
> > > Maybe I would recommend to use GRPharoUtf8Codec (although I like ZnUTF8Encoder more) or even better self codec (self = ZnZincServerAdaptor) to try to decode the bytes.
> > >
> > > Regards,
> > > Tomas Kukol
> > > _______________________________________________
> > > seaside mailing list
> > > [hidden email]
> > > http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
> >
> >
> >
> > --
> > Sven Van Caekenberghe
> > http://stfx.eu
> > Smalltalk is the Red Pill
> >
> > _______________________________________________
> > seaside mailing list
> > [hidden email]
> > http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
> >
> > _______________________________________________
> > seaside mailing list
> > [hidden email]
> > http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Zinc-Seaside: Problem with POSTing UTF-8 JSON

Philippe Marschall
On Wed, Jun 26, 2013 at 6:37 PM, Sven Van Caekenberghe <[hidden email]> wrote:
> Tomas,
>
> I am not sure what one is supposed to return from #getUsers.
>
> Naively, I would guess just a [Wide]String with the <produces: 'application/json; charset=utf-8'> telling the Seaside-REST framework to do the right thing, but I just don't know.

Yes it does/should, see

WARestfulHandler/Filter >> #executeResult:

Cheers
Philippe
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Zinc-Seaside: Problem with POSTing UTF-8 JSON

Sven Van Caekenberghe-2

On 26 Jun 2013, at 18:47, Philippe Marschall <[hidden email]> wrote:

> On Wed, Jun 26, 2013 at 6:37 PM, Sven Van Caekenberghe <[hidden email]> wrote:
>> Tomas,
>>
>> I am not sure what one is supposed to return from #getUsers.
>>
>> Naively, I would guess just a [Wide]String with the <produces: 'application/json; charset=utf-8'> telling the Seaside-REST framework to do the right thing, but I just don't know.
>
> Yes it does/should, see
>
> WARestfulHandler/Filter >> #executeResult:

I see. Tomas, can you trace in there and see what happens in your case ?

> Cheers
> Philippe
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Zinc-Seaside: Problem with POSTing UTF-8 JSON

Tomas Kukol
Hello, guys. Thanks for a great help.

I created these methods to check it:

GPRestfulHandler(WARestfulHandler)>>executeResult: aRouteResult
| result |
self requestContext
respond: [ :response | 
result := aRouteResult sendMessageTo: self.
response document: result mimeType: aRouteResult seasideMimeType ]

1) First one with simple Czech string:

GPRestfulHandler(WARestfulHandler)>>czechTestReal
<get>
<path: 'czechTestReal'>
<produces: 'application/json; charset=utf-8'>
^ 'Czech is in Czech čeština.' asJson

2) Second one with simple ascii string:

GPRestfulHandler(WARestfulHandler)>>czechTestReal
<get>
<path: 'czechTestReal'>
<produces: 'application/json; charset=utf-8'>
^ 'Czech is in Czech cestina.' asJson

1) In first case in executeResult: method in result variable is WideString 'Czech is in Czech čeština.'

I can see on the screen this error although I have WAException filter set to WAWalbackErrorHandler.
Error: Improper store into indexable object
2) In second case in executeResult: method in result variable is ByteString 'Czech is in Czech cestina.'
I can see on the screen expected result:
"Czech is in Czech cestina."
So, there must be somewhere a difference between ByteString and WideString conversion. I located the problem (thrown error) in this method:
ZnZincServerAdaptor>>responseFrom: aRequestContext
| partialHeaders cookies fullHeaders seasideResponse contents entity contentType |
seasideResponse := aRequestContext response.
partialHeaders := seasideResponse headers.
cookies := seasideResponse cookies.
fullHeaders := ZnHeaders defaultResponseHeaders.
partialHeaders keysAndValuesDo: [ :key :value |
fullHeaders at: key put: value ].
cookies do: [ :each |
fullHeaders at: 'Set-Cookie' add: each oldNetscapeString.
fullHeaders at: 'Set-Cookie2' add: each rfc2965String ].
contentType := seasideResponse contentType greaseString.
contents := seasideResponse contents. "<------------------------ HERE is the error signalled"
entity := (ZnEntity bytes: contents) contentType: contentType; yourself.
^ ZnResponse new
statusLine: (ZnStatusLine code: seasideResponse status);
headers: fullHeaders;
entity: entity;
yourself

Regards,
Tomas


On Wed, Jun 26, 2013 at 7:28 PM, Sven Van Caekenberghe <[hidden email]> wrote:

On 26 Jun 2013, at 18:47, Philippe Marschall <[hidden email]> wrote:

> On Wed, Jun 26, 2013 at 6:37 PM, Sven Van Caekenberghe <[hidden email]> wrote:
>> Tomas,
>>
>> I am not sure what one is supposed to return from #getUsers.
>>
>> Naively, I would guess just a [Wide]String with the <produces: 'application/json; charset=utf-8'> telling the Seaside-REST framework to do the right thing, but I just don't know.
>
> Yes it does/should, see
>
> WARestfulHandler/Filter >> #executeResult:

I see. Tomas, can you trace in there and see what happens in your case ?

> Cheers
> Philippe
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside


_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Zinc-Seaside: Problem with POSTing UTF-8 JSON

Tomas Kukol
Unbelievable, this code with Czech characters and MIME type set to text/json works well:

GPRestfulHandler(WARestfulHandler)>>czechTestReal
<get>
<path: 'czechTestReal'>
<produces: 'text/json; charset=utf-8'>
^ 'Czech is in Czech čeština.' asJson

This code with Czech characters and MIME type set to application/json throws an error.

GPRestfulHandler(WARestfulHandler)>>czechTestReal
<get>
<path: 'czechTestReal'>
<produces: 'application/json; charset=utf-8'>
^ 'Czech is in Czech čeština.' asJson

There is difference only in produces - text/json vs. application/json, but there are probably different stream - text vs. binary.

Tomas

On Wed, Jun 26, 2013 at 10:35 PM, Tomas Kukol <[hidden email]> wrote:
Hello, guys. Thanks for a great help.

I created these methods to check it:

GPRestfulHandler(WARestfulHandler)>>executeResult: aRouteResult
| result |
self requestContext
respond: [ :response | 
result := aRouteResult sendMessageTo: self.
response document: result mimeType: aRouteResult seasideMimeType ]

1) First one with simple Czech string:

GPRestfulHandler(WARestfulHandler)>>czechTestReal
<get>
<path: 'czechTestReal'>
<produces: 'application/json; charset=utf-8'>
^ 'Czech is in Czech čeština.' asJson

2) Second one with simple ascii string:

GPRestfulHandler(WARestfulHandler)>>czechTestReal
<get>
<path: 'czechTestReal'>
<produces: 'application/json; charset=utf-8'>
^ 'Czech is in Czech cestina.' asJson

1) In first case in executeResult: method in result variable is WideString 'Czech is in Czech čeština.'

I can see on the screen this error although I have WAException filter set to WAWalbackErrorHandler.
Error: Improper store into indexable object
2) In second case in executeResult: method in result variable is ByteString 'Czech is in Czech cestina.'
I can see on the screen expected result:
"Czech is in Czech cestina."
So, there must be somewhere a difference between ByteString and WideString conversion. I located the problem (thrown error) in this method:
ZnZincServerAdaptor>>responseFrom: aRequestContext
| partialHeaders cookies fullHeaders seasideResponse contents entity contentType |
seasideResponse := aRequestContext response.
partialHeaders := seasideResponse headers.
cookies := seasideResponse cookies.
fullHeaders := ZnHeaders defaultResponseHeaders.
partialHeaders keysAndValuesDo: [ :key :value |
fullHeaders at: key put: value ].
cookies do: [ :each |
fullHeaders at: 'Set-Cookie' add: each oldNetscapeString.
fullHeaders at: 'Set-Cookie2' add: each rfc2965String ].
contentType := seasideResponse contentType greaseString.
contents := seasideResponse contents. "<------------------------ HERE is the error signalled"
entity := (ZnEntity bytes: contents) contentType: contentType; yourself.
^ ZnResponse new
statusLine: (ZnStatusLine code: seasideResponse status);
headers: fullHeaders;
entity: entity;
yourself

Regards,
Tomas


On Wed, Jun 26, 2013 at 7:28 PM, Sven Van Caekenberghe <[hidden email]> wrote:

On 26 Jun 2013, at 18:47, Philippe Marschall <[hidden email]> wrote:

> On Wed, Jun 26, 2013 at 6:37 PM, Sven Van Caekenberghe <[hidden email]> wrote:
>> Tomas,
>>
>> I am not sure what one is supposed to return from #getUsers.
>>
>> Naively, I would guess just a [Wide]String with the <produces: 'application/json; charset=utf-8'> telling the Seaside-REST framework to do the right thing, but I just don't know.
>
> Yes it does/should, see
>
> WARestfulHandler/Filter >> #executeResult:

I see. Tomas, can you trace in there and see what happens in your case ?

> Cheers
> Philippe
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside



_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Zinc-Seaside: Problem with POSTing UTF-8 JSON

Sven Van Caekenberghe-2
Hi Tomas,

On 26 Jun 2013, at 22:46, Tomas Kukol <[hidden email]> wrote:

> Unbelievable, this code with Czech characters and MIME type set to text/json works well:
>
> GPRestfulHandler(WARestfulHandler)>>czechTestReal
> <get>
> <path: 'czechTestReal'>
> <produces: 'text/json; charset=utf-8'>
> ^ 'Czech is in Czech čeština.' asJson
>
> This code with Czech characters and MIME type set to application/json throws an error.
>
> GPRestfulHandler(WARestfulHandler)>>czechTestReal
> <get>
> <path: 'czechTestReal'>
> <produces: 'application/json; charset=utf-8'>
> ^ 'Czech is in Czech čeština.' asJson
>
> There is difference only in produces - text/json vs. application/json, but there are probably different stream - text vs. binary.

Great that you found it !

Indeed, consider:

(WAMimeType fromString: 'text/json') isBinary. false
(WAMimeType fromString: 'application/json') isBinary. true

(ZnMimeType fromString: 'text/json') isBinary. false
(ZnMimeType fromString: 'application/json') isBinary. false

I made an explicit exception for application/json in ZnMimeType ;-)

Sven

> Tomas
>
> On Wed, Jun 26, 2013 at 10:35 PM, Tomas Kukol <[hidden email]> wrote:
> Hello, guys. Thanks for a great help.
>
> I created these methods to check it:
>
> GPRestfulHandler(WARestfulHandler)>>executeResult: aRouteResult
> | result |
> self requestContext
> respond: [ :response |
> result := aRouteResult sendMessageTo: self.
> response document: result mimeType: aRouteResult seasideMimeType ]
>
> 1) First one with simple Czech string:
>
> GPRestfulHandler(WARestfulHandler)>>czechTestReal
> <get>
> <path: 'czechTestReal'>
> <produces: 'application/json; charset=utf-8'>
> ^ 'Czech is in Czech čeština.' asJson
>
> 2) Second one with simple ascii string:
>
> GPRestfulHandler(WARestfulHandler)>>czechTestReal
> <get>
> <path: 'czechTestReal'>
> <produces: 'application/json; charset=utf-8'>
> ^ 'Czech is in Czech cestina.' asJson
>
> 1) In first case in executeResult: method in result variable is WideString 'Czech is in Czech čeština.'
>
> I can see on the screen this error although I have WAException filter set to WAWalbackErrorHandler.
> Error: Improper store into indexable object
> 2) In second case in executeResult: method in result variable is ByteString 'Czech is in Czech cestina.'
> I can see on the screen expected result:
> "Czech is in Czech cestina."
> So, there must be somewhere a difference between ByteString and WideString conversion. I located the problem (thrown error) in this method:
> ZnZincServerAdaptor>>responseFrom: aRequestContext
>
>
>
> | partialHeaders cookies fullHeaders seasideResponse contents entity contentType |
>
>
>
> seasideResponse := aRequestContext response.
>
>
>
> partialHeaders := seasideResponse headers.
>
>
>
> cookies := seasideResponse cookies.
>
>
>
> fullHeaders := ZnHeaders defaultResponseHeaders.
>
>
>
> partialHeaders keysAndValuesDo: [ :key :value |
>
>
>
> fullHeaders at: key put: value ].
>
>
>
> cookies do: [ :each |
> fullHeaders at: 'Set-Cookie' add: each oldNetscapeString.
> fullHeaders at: 'Set-Cookie2' add: each rfc2965String ].
> contentType := seasideResponse contentType greaseString.
> contents := seasideResponse contents. "<------------------------ HERE is the error signalled"
> entity := (ZnEntity bytes: contents) contentType: contentType; yourself.
> ^ ZnResponse new
> statusLine: (ZnStatusLine code: seasideResponse status);
>
>
>
> headers: fullHeaders;
> entity: entity;
> yourself
>
>
>
>
> Regards,
>
>
>
> Tomas
>
>
> On Wed, Jun 26, 2013 at 7:28 PM, Sven Van Caekenberghe <[hidden email]> wrote:
>
> On 26 Jun 2013, at 18:47, Philippe Marschall <[hidden email]> wrote:
>
> > On Wed, Jun 26, 2013 at 6:37 PM, Sven Van Caekenberghe <[hidden email]> wrote:
> >> Tomas,
> >>
> >> I am not sure what one is supposed to return from #getUsers.
> >>
> >> Naively, I would guess just a [Wide]String with the <produces: 'application/json; charset=utf-8'> telling the Seaside-REST framework to do the right thing, but I just don't know.
> >
> > Yes it does/should, see
> >
> > WARestfulHandler/Filter >> #executeResult:
>
> I see. Tomas, can you trace in there and see what happens in your case ?
>
> > Cheers
> > Philippe
> > _______________________________________________
> > seaside mailing list
> > [hidden email]
> > http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>
>
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Zinc-Seaside: Problem with POSTing UTF-8 JSON

NorbertHartl

Am 27.06.2013 um 00:01 schrieb Sven Van Caekenberghe <[hidden email]>:

> Hi Tomas,
>
> On 26 Jun 2013, at 22:46, Tomas Kukol <[hidden email]> wrote:
>
>> Unbelievable, this code with Czech characters and MIME type set to text/json works well:
>>
>> GPRestfulHandler(WARestfulHandler)>>czechTestReal
>> <get>
>> <path: 'czechTestReal'>
>> <produces: 'text/json; charset=utf-8'>
>> ^ 'Czech is in Czech čeština.' asJson
>>
>> This code with Czech characters and MIME type set to application/json throws an error.
>>
>> GPRestfulHandler(WARestfulHandler)>>czechTestReal
>> <get>
>> <path: 'czechTestReal'>
>> <produces: 'application/json; charset=utf-8'>
>> ^ 'Czech is in Czech čeština.' asJson
>>
>> There is difference only in produces - text/json vs. application/json, but there are probably different stream - text vs. binary.
>
> Great that you found it !
>
> Indeed, consider:
>
> (WAMimeType fromString: 'text/json') isBinary. false
> (WAMimeType fromString: 'application/json') isBinary. true
>
> (ZnMimeType fromString: 'text/json') isBinary. false
> (ZnMimeType fromString: 'application/json') isBinary. false
>
> I made an explicit exception for application/json in ZnMimeType ;-)
>
Everytime I see text/binary issues when one talks about character encoding it feels like there is something really wrong! I think the concept of text/binary streams is a legacy thing that we need to get rid of.

Norbert

> Sven
>
>> Tomas
>>
>> On Wed, Jun 26, 2013 at 10:35 PM, Tomas Kukol <[hidden email]> wrote:
>> Hello, guys. Thanks for a great help.
>>
>> I created these methods to check it:
>>
>> GPRestfulHandler(WARestfulHandler)>>executeResult: aRouteResult
>> | result |
>> self requestContext
>> respond: [ :response |
>> result := aRouteResult sendMessageTo: self.
>> response document: result mimeType: aRouteResult seasideMimeType ]
>>
>> 1) First one with simple Czech string:
>>
>> GPRestfulHandler(WARestfulHandler)>>czechTestReal
>> <get>
>> <path: 'czechTestReal'>
>> <produces: 'application/json; charset=utf-8'>
>> ^ 'Czech is in Czech čeština.' asJson
>>
>> 2) Second one with simple ascii string:
>>
>> GPRestfulHandler(WARestfulHandler)>>czechTestReal
>> <get>
>> <path: 'czechTestReal'>
>> <produces: 'application/json; charset=utf-8'>
>> ^ 'Czech is in Czech cestina.' asJson
>>
>> 1) In first case in executeResult: method in result variable is WideString 'Czech is in Czech čeština.'
>>
>> I can see on the screen this error although I have WAException filter set to WAWalbackErrorHandler.
>> Error: Improper store into indexable object
>> 2) In second case in executeResult: method in result variable is ByteString 'Czech is in Czech cestina.'
>> I can see on the screen expected result:
>> "Czech is in Czech cestina."
>> So, there must be somewhere a difference between ByteString and WideString conversion. I located the problem (thrown error) in this method:
>> ZnZincServerAdaptor>>responseFrom: aRequestContext
>>
>>
>>
>> | partialHeaders cookies fullHeaders seasideResponse contents entity contentType |
>>
>>
>>
>> seasideResponse := aRequestContext response.
>>
>>
>>
>> partialHeaders := seasideResponse headers.
>>
>>
>>
>> cookies := seasideResponse cookies.
>>
>>
>>
>> fullHeaders := ZnHeaders defaultResponseHeaders.
>>
>>
>>
>> partialHeaders keysAndValuesDo: [ :key :value |
>>
>>
>>
>> fullHeaders at: key put: value ].
>>
>>
>>
>> cookies do: [ :each |
>> fullHeaders at: 'Set-Cookie' add: each oldNetscapeString.
>> fullHeaders at: 'Set-Cookie2' add: each rfc2965String ].
>> contentType := seasideResponse contentType greaseString.
>> contents := seasideResponse contents. "<------------------------ HERE is the error signalled"
>> entity := (ZnEntity bytes: contents) contentType: contentType; yourself.
>> ^ ZnResponse new
>> statusLine: (ZnStatusLine code: seasideResponse status);
>>
>>
>>
>> headers: fullHeaders;
>> entity: entity;
>> yourself
>>
>>
>>
>>
>> Regards,
>>
>>
>>
>> Tomas
>>
>>
>> On Wed, Jun 26, 2013 at 7:28 PM, Sven Van Caekenberghe <[hidden email]> wrote:
>>
>> On 26 Jun 2013, at 18:47, Philippe Marschall <[hidden email]> wrote:
>>
>>> On Wed, Jun 26, 2013 at 6:37 PM, Sven Van Caekenberghe <[hidden email]> wrote:
>>>> Tomas,
>>>>
>>>> I am not sure what one is supposed to return from #getUsers.
>>>>
>>>> Naively, I would guess just a [Wide]String with the <produces: 'application/json; charset=utf-8'> telling the Seaside-REST framework to do the right thing, but I just don't know.
>>>
>>> Yes it does/should, see
>>>
>>> WARestfulHandler/Filter >> #executeResult:
>>
>> I see. Tomas, can you trace in there and see what happens in your case ?
>>
>>> Cheers
>>> Philippe
>>> _______________________________________________
>>> seaside mailing list
>>> [hidden email]
>>> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>>
>> _______________________________________________
>> seaside mailing list
>> [hidden email]
>> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>>
>>
>> _______________________________________________
>> seaside mailing list
>> [hidden email]
>> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Zinc-Seaside: Problem with POSTing UTF-8 JSON

Philippe Marschall
In reply to this post by Sven Van Caekenberghe-2
On Thu, Jun 27, 2013 at 12:01 AM, Sven Van Caekenberghe <[hidden email]> wrote:

> Hi Tomas,
>
> On 26 Jun 2013, at 22:46, Tomas Kukol <[hidden email]> wrote:
>
>> Unbelievable, this code with Czech characters and MIME type set to text/json works well:
>>
>> GPRestfulHandler(WARestfulHandler)>>czechTestReal
>>       <get>
>>       <path: 'czechTestReal'>
>>       <produces: 'text/json; charset=utf-8'>
>>       ^ 'Czech is in Czech čeština.' asJson
>>
>> This code with Czech characters and MIME type set to application/json throws an error.
>>
>> GPRestfulHandler(WARestfulHandler)>>czechTestReal
>>       <get>
>>       <path: 'czechTestReal'>
>>       <produces: 'application/json; charset=utf-8'>
>>       ^ 'Czech is in Czech čeština.' asJson
>>
>> There is difference only in produces - text/json vs. application/json, but there are probably different stream - text vs. binary.
>
> Great that you found it !
>
> Indeed, consider:
>
> (WAMimeType fromString: 'text/json') isBinary. false
> (WAMimeType fromString: 'application/json') isBinary. true
>
> (ZnMimeType fromString: 'text/json') isBinary. false
> (ZnMimeType fromString: 'application/json') isBinary. false
>
> I made an explicit exception for application/json in ZnMimeType ;-)

Good find, I created a bug [1]

 [1] http://code.google.com/p/seaside/issues/detail?id=759

Cheers
Philippe
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Zinc-Seaside: Problem with POSTing UTF-8 JSON

Philippe Marschall
In reply to this post by NorbertHartl
On Fri, Jun 28, 2013 at 8:51 AM, Norbert Hartl <[hidden email]> wrote:

>
> Am 27.06.2013 um 00:01 schrieb Sven Van Caekenberghe <[hidden email]>:
>
>> Hi Tomas,
>>
>> On 26 Jun 2013, at 22:46, Tomas Kukol <[hidden email]> wrote:
>>
>>> Unbelievable, this code with Czech characters and MIME type set to text/json works well:
>>>
>>> GPRestfulHandler(WARestfulHandler)>>czechTestReal
>>>      <get>
>>>      <path: 'czechTestReal'>
>>>      <produces: 'text/json; charset=utf-8'>
>>>      ^ 'Czech is in Czech čeština.' asJson
>>>
>>> This code with Czech characters and MIME type set to application/json throws an error.
>>>
>>> GPRestfulHandler(WARestfulHandler)>>czechTestReal
>>>      <get>
>>>      <path: 'czechTestReal'>
>>>      <produces: 'application/json; charset=utf-8'>
>>>      ^ 'Czech is in Czech čeština.' asJson
>>>
>>> There is difference only in produces - text/json vs. application/json, but there are probably different stream - text vs. binary.
>>
>> Great that you found it !
>>
>> Indeed, consider:
>>
>> (WAMimeType fromString: 'text/json') isBinary. false
>> (WAMimeType fromString: 'application/json') isBinary. true
>>
>> (ZnMimeType fromString: 'text/json') isBinary. false
>> (ZnMimeType fromString: 'application/json') isBinary. false
>>
>> I made an explicit exception for application/json in ZnMimeType ;-)
>>
> Everytime I see text/binary issues when one talks about character encoding it feels like there is something really wrong! I think the concept of text/binary streams is a legacy thing that we need to get rid of.

Yes, sometimes it is tempting to throw it all away and start all over
with XStreams.

Cheers
Philippe
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside