You are not logged in.
Pages: 1
Hi,
thanks for a great framework....
I am working on a REST communication with Wordpress ( via Wordpress plugin WP REST API with Oauth 1.0a authenification)
I would like to use the TSQLHttpClient class and CallBackGet function but I ran into troubles with limited GET parameters names - only ['a'..'z','A'..'Z'] charset is allowed in parameter names in mormot. However Oauth 1.0 requires parameters with underscores (f.e. oauth_signature,..).
Is it possible to add underscore into the allowed characters for parameter names?
here is the modification that could accomplish it... As you can see 1 line is changed.
function TSQLRestClientURI.CallBackGet(const aMethodName: RawUTF8;
const aNameValueParameters: array of const; out aResponse: RawUTF8;
aTable: TSQLRecordClass; aID: TID; aResponseHead: PRawUTF8): integer;
var url, header: RawUTF8;
begin
if self=nil then
result := HTML_UNAVAILABLE else begin
{$ifdef WITHLOG}
fLogClass.Enter(Self,pointer(aMethodName),true);
{$endif}
url := Model.getURICallBack(aMethodName,aTable,aID)+
UrlEncode(aNameValueParameters);
....
end;
end;
function UrlEncode(const NameValuePairs: array of const): RawUTF8;
// (['select','*','where','ID=12','offset',23,'object',aObject]);
var A, n: PtrInt;
name, value: RawUTF8;
function Invalid(P: PAnsiChar): boolean;
begin
result := true;
if P<>nil then begin
repeat
if not (P^ in ['a'..'z','_','A'..'Z']) then // <--- originally if not (P^ in ['a'..'z','A'..'Z'])
exit else
inc(P);
until P^=#0;
result := false;
end;
end;
begin
result := '';
n := high(NameValuePairs);
if n>0 then begin
for A := 0 to n shr 1 do begin
VarRecToUTF8(NameValuePairs[A*2],name);
if Invalid(pointer(name)) then
continue;
with NameValuePairs[A*2+1] do
if VType=vtObject then
value := ObjectToJSON(VObject,[]) else
VarRecToUTF8(NameValuePairs[A*2+1],value);
result := result+'&'+name+'='+UrlEncode(value);
end;
result[1] := '?';
end;
end;
Eva
Offline
The framework version you are using is clearly deprecated.
This has already been included in the trunk:
function UrlEncode(const NameValuePairs: array of const): RawUTF8;
// (['select','*','where','ID=12','offset',23,'object',aObject]);
var A, n: PtrInt;
name, value: RawUTF8;
function Invalid(P: PAnsiChar): boolean;
begin
result := true;
if P<>nil then begin
repeat // cf. rfc3986 2.3. Unreserved Characters
if not (P^ in ['a'..'z','A'..'Z','0'..'9','_','.','~']) then
exit else
inc(P);
until P^=#0;
result := false;
end;
end;
Ensure you use the latest "unstable" version, not the "stable" version which is clearly deprecated.
See http://synopse.info/files/html/Synopse% … l#TITL_113
Offline
o, sorry, thanks for the info...
But I ran into another problem ( this time I have checked (to be the sure) in the latest unstable version too)
The problem is still related to the TSQLHttpClient. I would like to set both the Content-Type and also Cookies in the request.
something like
lHead := 'Content-Type: application/x-www-form-urlencoded;charset=UTF-8'+#13#10 +
'Cookie: a=1111111111' ;
But InternalURI works like this: if Header contains any Content-type then all other settings in Header are neglected
( // header is processed -> no need to send Content-Type twice )
procedure TSQLHttpClientGeneric.InternalURI(var Call: TSQLRestURIParams);
var Head, Content, ContentType: RawUTF8;
P: PUTF8Char;
begin
..
Head := Call.InHead;
Content := Call.InBody;
if InternalCheckOpen then begin
if Head<>'' then begin
P := pointer(Head);
if IdemPChar(P,'CONTENT-TYPE:') then begin
inc(P,14);
if Content<>'' then begin
ContentType := GetMimeContentType(pointer(Content),Length(Content));
if ContentType='application/octet-stream' then
ContentType := '';
end;
if ContentType='' then
ContentType := GetNextLine(P,PEnd);
Head := ''; // header is processed -> no need to send Content-Type twice
end;
end;
IMHO it would cause trouble also in the case when TSQLHttpClient has set both Content-Type and fSessionHttpHeader
It is possible to preserve other settings in Header?
at least something like this: ( I maybe wrong )
procedure TSQLHttpClientGeneric.InternalURI(var Call: TSQLRestURIParams);
var Head, Content, ContentType, lContentypeInHead: RawUTF8;
P,PBegin, pEnd: PUTF8Char;
begin
...
Head := Call.InHead;
Content := Call.InBody;
if InternalCheckOpen then begin
if Head<>'' then begin
P := pointer(Head);
if IdemPChar(P,'CONTENT-TYPE:') then begin
PBegin := P; // <--- added
inc(P,14);
lContentypeInHead := GetNextLine(P,PEnd); // <--- added
if Content<>'' then begin
ContentType := GetMimeContentType(pointer(Content),Length(Content));
if ContentType='application/octet-stream' then
ContentType := '';
end;
if ContentType='' then
ContentType := lContentypeInHead; // <--- changed
system.delete(Head, PBegin - pointer(Head) + 1, pEnd-pBegin ); // <--- added
end;
end;
...
end;
P.S. I have just checked the IdemPChar function - "Content-Type" should be the first parameter in the request-header because of using this IdemPChar function
Last edited by EvaF (2015-12-21 11:35:53)
Offline
Should be fixed by http://synopse.info/fossil/info/8ede0e28bb
Thanks for the feedback!
Offline
hi ab,
thanks for modification - the last wish (hope) is replacing IdemPChar function by some Pos function ( f.e. StrPosI function)
for the case:
lHead := 'Cookie: a=1111111111' +#13#10 +
'Content-Type: application/x-www-form-urlencoded;charset=UTF-8';
can look something like this:
if InternalCheckOpen then begin
if Head<>'' then begin
P := pointer(Head);
P := StrPosI('CONTENT-TYPE:',P);
if assigned(P) then begin
PBegin := P;
inc(P,14);
lContentypeInHead := GetNextLine(P,PEnd);
if not assigned(pEnd) then // Content-type parameter is the last
begin
pEnd := Pointer(Head);
Inc(pEnd, length(Head));
end;
system.delete(Head, PBegin - pointer(Head) + 1, pEnd-pBegin );
...
thanks again
ef
Offline
Using StrPosI() may be unsafe, since the text may appear as part of a header value, not as a header entry name...
Please try http://synopse.info/fossil/info/241300a272 which sounds safer.
It would let TSQLHttpClientGeneric.InternalURI recognize Content-Type: header on any position.
Offline
Using StrPosI() may be unsafe, since the text may appear as part of a header value, not as a header entry name...
You are right, I will use it your way, thx
ef
Offline
only small question - I cannot find GetMimeContentTypeFromBuffer function
I suppose that it looks something like that:
function GetMimeContentTypeFromBuffer(Content: Pointer; Len: integer;
const ContentType: RawUTF8 =''): RawUTF8;
begin
Result := GetMimeContentType(Content, Len);
if (Result = '') or (Result = 'application/octet-stream') then
Result := ContentType;
end;
Offline
ok, thanks for everything
Offline
Pages: 1