Lazarus

Programming => Networking and Web Programming => Topic started by: zyzmo on February 12, 2018, 07:34:14 pm

Title: Webservice with TTCPBlockSocket
Post by: zyzmo on February 12, 2018, 07:34:14 pm
Hello!

I'm stuck on a webservice functionality, I'd like to know how can I read the headers sent by a remote page...

I'm developing a webservice with synapse as shown here:http://wiki.freepascal.org/Networking#Webserver_example (http://wiki.freepascal.org/Networking#Webserver_example). I'm making the request through a web app(POST) sending data via headers(JSON), so in the server side I need to read this data to execute a  function...

Thanks in advance
Title: Re: Webservice with TTCPBlockSocket
Post by: Leledumbo on February 14, 2018, 05:40:53 am
The example already shows you, it's `ASocket.RecvString` inside the repeat-until loop. Note that example is a webSERVER, while you mention webSERVICE here, which is one level above it.
Title: Re: Webservice with TTCPBlockSocket
Post by: zyzmo on February 14, 2018, 12:32:30 pm
Well, That was I thought, but I'm passing headers via AJAX and it doesn't work! :(

I've tried in many ways without success...
Just to be clear I'm using TTCPBlockSocket to provide a webservice which will be consumed via webapp (I'm using Angular 2). That webservice works as well, but I'm trying to pass some headers but those headers just disappear when data received at TTCPBlockSocket...

PS: The Http headers into Angular side are going right... I double checked it as well
Title: Re: Webservice with TTCPBlockSocket
Post by: rvk on February 14, 2018, 12:43:15 pm
I'm making the request through a web app(POST) sending data via headers(JSON), so in the server side I need to read this data to execute a  function...
The JSON doesn't go "via the headers". In the headers there is a Content-Type specified and the actual JSON is send as data just under the headers.

What do you get as headers in AttendConnection()?
The ASocket.RecvString() should just receive headers first.

(And how did you check on the Angular side that the headers were sent?)
Title: Re: Webservice with TTCPBlockSocket
Post by: zyzmo on February 14, 2018, 01:31:21 pm
Here is the headers

Host: 192.168.0.12:8080
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: http://localhost:8100
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.167 Safari/537.36
Access-Control-Request-Headers: access-control-allow-origin,content-type,filter
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7

Well in bold are the parameters I sent via request, but I cant head which values I put in those parameters...

Title: Re: Webservice with TTCPBlockSocket
Post by: rvk on February 14, 2018, 01:39:27 pm
Access-Control-Request-Method: GET
This seems like a GET method.
If you say you post a JSON via Angular, I wonder what happened to the POST headers.
There is no POST, there is no Content-Type and Length and there is no JSON data.

What were the sending headers you got in Angular?
What code do you use in Angular for that AJAX call?
Title: Re: Webservice with TTCPBlockSocket
Post by: zyzmo on February 14, 2018, 01:48:49 pm
Quote
What were the sending headers you got in Angular?
const headers = new HttpHeaders()
.append("Access-Control-Allow-Origin","*")
.append('Content-Type', 'application/json')
.append('Filter', 'Hello World');

Quote
What code do you use in Angular for that AJAX call?
this.http.get('http://192.168.0.12:8080/lol', {headers}).subscribe((res) => {
      console.log(res);                 
});

So I know that headers are being sent because of this line:
Access-Control-Request-Headers: access-control-allow-origin,content-type,filter
However I cant read the entire Headers, with the parameters value... As far as I know (using javascript) in the webservice I just read the request header and get all the stuff needed...
Title: Re: Webservice with TTCPBlockSocket
Post by: rvk on February 14, 2018, 01:53:42 pm
Quote
What code do you use in Angular for that AJAX call?
this.http.get('http://192.168.0.12:8080/lol', {headers}).subscribe((res) => {
      console.log(res);                 
});
I wonder if Angular filters out some of the headers because this is a GET, not a POST.

Besides that... after googling for 30 seconds I found this:
https://github.com/angular/angular/issues/19044
So maybe using .append() doesn't work as you expected.

As I see it .append is a function which returns httpheaders. So you should do something like this:
let headers = new HttpHeaders();
headers = headers.append('Authorization', this.authHeader);
headers = headers.append('Accept', 'application/json');
headers = headers.append('Content-Type', 'application/json');
Title: Re: Webservice with TTCPBlockSocket
Post by: zyzmo on February 14, 2018, 02:09:23 pm
Neither POST nor GET methods give me the entire request header... As I said the header property is sent, but I can't get the values... could be that I'm using the wrong function, I really don't know how to get the full header values!

Here is the POST headers:

Host: 192.168.0.12:8080
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://localhost:8100
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.167 Safari/537.36
Access-Control-Request-Headers: access-control-allow-origin,content-type,filter
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7

Title: Re: Webservice with TTCPBlockSocket
Post by: rvk on February 14, 2018, 02:23:17 pm
Maybe you specified the headers but they are definitely not sent because otherwise they would be received at the other end.

Also notice that your Access-Control-Request-Headers contains the header-titles you wanted to send:
Access-Control-Request-Headers: access-control-allow-origin,content-type,filter
Do you see that "filter" at the end.
So I think you are using .append the wrong way.
(Maybe .append is only used as string function and not function for headers.)

Did you try setting the headers with the following?
let headers = new HttpHeaders();
headers = headers.append('Filter', 'Hello World');

That way you are sure the .append of headers is used as function and not a string.append function.
Title: Re: Webservice with TTCPBlockSocket
Post by: zyzmo on February 14, 2018, 02:36:06 pm
Quote
Did you try setting the headers with the following?
let headers = new HttpHeaders();
headers = headers.append('Filter', 'Hello World');

Yes, I did... But doesn't work! The same methods works with a javascript webservice! I've tried in several ways but without success ...

The weird thing is (as you said) the header-title are there but no data!
Title: Re: Webservice with TTCPBlockSocket
Post by: rvk on February 14, 2018, 02:44:59 pm
The weird thing is (as you said) the header-title are there but no data!
Yes, but those header-titles are not really headers. They are appended to Access-Control-Request-Headers. So something puts those headers into that single Access-Control-Request-Headers.

Access-Control-Request-Headers: access-control-allow-origin,content-type,filter
All I can see is that Access-Control-Request-Headers is used in a preflight request.

I did find some information here:
https://stackoverflow.com/questions/34264482/http-headers-gets-added-under-access-control-request-headers

Ah, here it is:
Quote
The preflight is being triggered by your Content-Type of application/json. The simplest way to prevent this is to set the Content-Type to be text/plain in your case. application/x-www-form-urlencoded & multipart/form-data Content-Types are also acceptable, but you'll of course need to format your request payload appropriately.

If you are still seeing a preflight after making this change, then Angular may be adding an X-header to the request as well.
https://stackoverflow.com/questions/22968406/how-to-skip-the-options-preflight-request-in-angularjs

Did you try removing the Content-Type line or changing the application/json to something else?

Another option would be to answer correctly to that "preflight request" after which the client will send the real request with all the headers.

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Preflighted_requests
Quote
Unlike “simple requests” (discussed above), "preflighted" requests first send an HTTP request by the OPTIONS method to the resource on the other domain, in order to determine whether the actual request is safe to send. Cross-site requests are preflighted like this since they may have implications to user data.
Title: Re: Webservice with TTCPBlockSocket
Post by: zyzmo on February 14, 2018, 06:09:52 pm
That's right ! using  "content-type: text/plain" the function worked properly !

Another thing that I found was that TTCPBlockSocket don't accept any header attribute!

I think in that point I can keep going with my test!

Thank you so much !!!
Title: Re: Webservice with TTCPBlockSocket
Post by: rvk on February 14, 2018, 06:14:07 pm
Another thing that I found was that TTCPBlockSocket don't accept any header attribute!
What do you mean?
TTCPBlockSocket doesn't know anything about "headers". It just receives clean data. The data itself should consists of the complete headers and data (separated by a blank line). But TTCPBlockSocket isn't a HTTP-component. So you are dealing with raw data. It accepts all that data.
Title: Re: Webservice with TTCPBlockSocket
Post by: zyzmo on February 14, 2018, 06:48:17 pm
Quote
What do you mean?
I meant  that the component doesn't work with some header attributes, like I tried execute a post passing "Access-Control-Allow-Origin","*", with that the header looks like as I said previously... So, without that header it works fine! I just had to change the "Content-Type" to "text/plain";

Well, it's  my first experience with this kind of function using Laz/FPC, and that was the way that I found to solve the problem! Probably there is an easiest way to do it...

But TTCPBlockSocket isn't a HTTP-component. So you are dealing with raw data. It accepts all that data.
Do you know any HTTP component which I could build a webservice or anything like that? I mean "easier" to work with HTTP requests?
Title: Re: Webservice with TTCPBlockSocket
Post by: SymbolicFrank on February 14, 2018, 07:25:24 pm
How does a http message actually looks like?

Code: Pascal  [Select][+][-]
  1. Header1: Value1
  2. Header2: Value2
  3. Header3: Value3
  4.  
  5. This is the message, it can contain just about any legal UTF-8 char.
  6. And line breaks, of course.
  7. Note the empty line above the message, that's how you know where it starts.
  8.  

And this is what you receive. Everything else is a question of formatting. And the JSON would be the message, or inside <html><head/><body>JSON</body></html> tags, depending.
Title: Re: Webservice with TTCPBlockSocket
Post by: Renat.Su on February 14, 2018, 07:27:04 pm
TFPHTTPServer (fcl-web), synapse, BrookFramework
Quote
any HTTP component which I could build a webservice or anything like that? I mean "easier" to work with HTTP requests?
Title: Re: Webservice with TTCPBlockSocket
Post by: zyzmo on February 14, 2018, 08:03:45 pm
How does a http message actually looks like?
[...]
And this is what you receive. Everything else is a question of formatting. And the JSON would be the message, or inside <html><head/><body>JSON</body></html> tags, depending.

I already found the resolution with rvk orientation! It was like TTCPBlockSocket don't accept "content-type: application/json" so I replaced it to "content-type: text/plain" and worked as expected!

Thanks for answer! 
Title: Re: Webservice with TTCPBlockSocket
Post by: rvk on February 14, 2018, 08:07:36 pm
Well, it's  my first experience with this kind of function using Laz/FPC, and that was the way that I found to solve the problem! Probably there is an easiest way to do it...
Well, the problem lied on the client side. Angular (or the browser) first sends an OPTION request before sending the real GET or POST. That's because you added the custom headers. If you didn't, or you change the content-type, the GET or POST is sent directly. That's why it would also be an option to send an OK back to the client and wait for the actual GET or POST. It's really annoying that extra OPTION request is sent, but I don't know how to disable it easily, other than sending text/plain as content-type.

Quote
Do you know any HTTP component which I could build a webservice or anything like that? I mean "easier" to work with HTTP requests?
Synapse does not have such HTTP-server component. Indy does. But I'm not sure if Indy takes these pre-flight OPTION requests into account.

The best option would be to respons to the OPTION request with a HTTP/1.1 200 OK. After that you would get the actual GET. Then you're "server" would behave like it should.

Using text/plain will work fine too if you are sure the client always uses that.
Title: Re: Webservice with TTCPBlockSocket
Post by: rvk on February 14, 2018, 08:33:27 pm
F.Y.I. here is some information how you would respond to an OPTION request:
https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request
Title: Re: Webservice with TTCPBlockSocket
Post by: zyzmo on February 14, 2018, 09:30:51 pm
F.Y.I. here is some information how you would respond to an OPTION request:
https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request
I'll read it!

Thanks!
TinyPortal © 2005-2018