Webservice with TTCPBlockSocket lazarus / 38-Networking and Web Programming ---------------------------------------------------------------------- zyzmo · 2018-02-12 18:34 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. 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 ---------------------------------------------------------------------- Leledumbo · 2018-02-14 04:40 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. ---------------------------------------------------------------------- zyzmo · 2018-02-14 11:32 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 ---------------------------------------------------------------------- rvk · 2018-02-14 11:43 Quote from: zyzmo on February 12, 2018, 07:34:14 pmI'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?) ---------------------------------------------------------------------- zyzmo · 2018-02-14 12:31 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... ---------------------------------------------------------------------- rvk · 2018-02-14 12:39 Quote from: zyzmo on February 14, 2018, 01:31:21 pmAccess-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? ---------------------------------------------------------------------- zyzmo · 2018-02-14 12:48 QuoteWhat 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'); QuoteWhat 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... ---------------------------------------------------------------------- rvk · 2018-02-14 12:53 Quote from: zyzmo on February 14, 2018, 01:48:49 pmQuoteWhat 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'); ---------------------------------------------------------------------- zyzmo · 2018-02-14 13:09 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 ---------------------------------------------------------------------- rvk · 2018-02-14 13:23 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. ---------------------------------------------------------------------- zyzmo · 2018-02-14 13:36 QuoteDid 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! ---------------------------------------------------------------------- rvk · 2018-02-14 13:44 Quote from: zyzmo on February 14, 2018, 02:36:06 pmThe 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: QuoteThe 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 QuoteUnlike “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. ---------------------------------------------------------------------- zyzmo · 2018-02-14 17:09 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 !!! ---------------------------------------------------------------------- rvk · 2018-02-14 17:14 Quote from: zyzmo on February 14, 2018, 06:09:52 pmAnother 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. ---------------------------------------------------------------------- zyzmo · 2018-02-14 17:48 QuoteWhat 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... Quote from: rvk on February 14, 2018, 06:14:07 pm 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? ---------------------------------------------------------------------- SymbolicFrank · 2018-02-14 18:25 How does a http message actually looks like? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Header1: Value1Header2: Value2Header3: Value3 This is the message, it can contain just about any legal UTF-8 char.And line breaks, of course.Note the empty line above the message, that's how you know where it starts.  And this is what you receive. Everything else is a question of formatting. And the JSON would be the message, or inside JSON tags, depending. ---------------------------------------------------------------------- Renat.Su · 2018-02-14 18:27 TFPHTTPServer (fcl-web), synapse, BrookFramework Quoteany HTTP component which I could build a webservice or anything like that? I mean "easier" to work with HTTP requests? ---------------------------------------------------------------------- zyzmo · 2018-02-14 19:03 Quote from: SymbolicFrank on February 14, 2018, 07:25:24 pmHow 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 JSON 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! ---------------------------------------------------------------------- rvk · 2018-02-14 19:07 Quote from: zyzmo on February 14, 2018, 06:48:17 pmWell, 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. QuoteDo 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. ---------------------------------------------------------------------- rvk · 2018-02-14 19:33 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 ---------------------------------------------------------------------- zyzmo · 2018-02-14 20:30 Quote from: rvk on February 14, 2018, 08:33:27 pmF.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!