Free Pascal - Post data to dweet.io with colon in URL

105 views Asked by At

I am playing arround with https://dweet.io/ - the concept is that you can send/post some fields/values to dweet.io and you can see those values published directly there or even see those data as graphical gauges in https://freeboard.io/. For the former no registration is required; data is published directly.

Example with curl:

$curl 'https://dweet.io/dweet/for/:kpv1?volt1=622&volt2=624&volt3=600'
#response:
{"this":"succeeded","by":"dweeting","the":"dweet","with":{"thing":":kpv1","created":"2023-11-05T19:03:17.892Z","content":{"volt1":622,"volt2":624,"volt3":600},"transaction":"98967dcf-168d-4c78-a190-9476ff95e9cd"}}

The same result can be achieved if I enter in my browser the URL https://dweet.io/dweet/for/:kpv1?volt1=622&volt2=624&volt3=600. Visiting https://dweet.io/follow/:kpv1 shows the data posted previously.

I would like to make this function through Free Pascal/Lazarus using a simple post solution. I have tried below code in a simple GUI form with a TEdit and a TButton, but when I press the button nothing happens... dweet.io is not updated and my Edit1.Text remains empty. Also i got nothing on stderr.

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, opensslsockets, fphttpclient;
type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
  private

  public

  end;

var
  Form1: TForm1;
  URL, S : String;

implementation

{$R *.lfm}

{ TForm1 }                            
procedure TForm1.Button1Click(Sender: TObject);
begin
  URL := 'https://dweet.io/dweet/for/:kpv1?volt1=922&volt2=924&volt3=900';
    S := TFPCustomHTTPClient.SimplePost(URL);
  Writeln(stderr, S);
  Edit1.Text:=S;
end;  

Any ideas what I am missing...?

Update:

Ok, the problem is the "thing" name that I was using in dweet.io. For a "thing" named :kpv1 the code breaks. If I change the name to kpv1 (removing the : char) the code works fine. So these two lines works fine when the colon is removed from kpv1:

URL := 'https://dweet.io/dweet/for/kpv1?volt1=922&volt2=924&volt3=900';
S := TFPCustomHTTPClient.SimplePost(URL);
// response received in Edit1.Text:
// {"this":"succeeded","by":"dweeting","the":"dweet","with":{"thing":"kpv1","created":"2023-11-05T20:09:47.833Z","content":{"volt1":922,"volt2":924,"volt3":900},"transaction":"7177dc55-a174-4edd-b88d-fd64cc4dad9f"}}
// Values posted to dweet.io for kpv1 can be visualized in address https://dweet.io/follow/kpv1    
1

There are 1 answers

0
AmigoJack On

The problem is that you don't respect how a URI/URL in HTTP has to be constructed - in there the colon is a reserved character as per RFC 3986 and needs to be percent-encoded into %3A when being part of the path, query, or fragmet/anchor. The same rule applies to other selected characters, too (especially if you want to express things like a whitespace or a slash / or and ampersand & or a question mark ?).

So the whole remedy should be:

URL := 'https://dweet.io/dweet/for/%3Akpv1?volt1=922&volt2=924&volt3=900';

...which is unbound to FreePascal and dweet.io - it applies to HTTP knowledge. I'll add respective tags to your Q.

In FreePascal httpprotocol.HTTPEncode() looks sane in terms of implementation, so you could do in general:

uses
  httpprotocol;
begin
  URL:= 'https://dweet.io/dweet/for/'  // protocol + domain + path
      + HTTPEncode( ':Akpv1' )  // resource
      + '?volt1='+ HTTPEncode( '922' )  // first parameter
      + '&volt2='+ HTTPEncode( '924' )  // second parameter
      + '&volt3='+ HTTPEncode( '900' )  // third parameter
      ;

Note: encode components of the URL, not the whole URL in general.