{ This file is part of restemplate. Copyright (C) 2015 Andreas Schneider restemplate is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. sqlvision is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with restemplate. If not, see . } program restemplate; {.$define use_synapse} {$define use_fclweb} uses SysUtils, Classes, strutils, IniFiles, {$ifdef use_synapse}httpsend, ssl_openssl,{$endif} {$ifdef use_fclweb}fphttpclient,{$endif} JTemplate, fpjson, jsonparser; var data: TextFile; line: String; parser: TJTemplateParser; {$ifdef use_synapse}http: THTTPSend;{$endif} {$ifdef use_fclweb}http: TFPHTTPClient;{$endif} method, url: String; content: TStringList; commandMode: Boolean; configDir, templateDir: String; templateFile, templateName: String; sessionIni: TIniFile; beautify: Boolean; procedure CmdAskUser(AName: String); var value, default: String; begin Write(AName); default := sessionIni.ReadString(templateName, AName, ''); if default <> '' then Write(' [', default, ']: ') else Write(': '); ReadLn(value); if value = '' then value := default; parser.Fields.Add(AName, value); sessionIni.WriteString(templateName, AName, value); end; procedure CmdHeader(AHeader: String); var i: Integer; name, value: String; begin parser.Content := AHeader; parser.Replace; {$ifdef use_synapse} http.Headers.Add(parser.Content); {$endif} {$ifdef use_fclweb} i := 1; while (i < Length(AHeader)) and (AHeader[i] <> ':') do Inc(i); name := Trim(Copy(AHeader, 1, i - 1)); value := Trim(Copy(AHeader, i + 1, Length(AHeader))); http.AddHeader(name, value); {$endif} end; procedure ProcessCall(AURL: String); var s: String; {$ifdef use_fclweb} request, response: TStream; {$endif} jsonParser: TJSONParser; jsonData: TJSONData; begin parser.Content := AURL; parser.Replace; AURL := parser.Content; writeln('Calling ', AURL); {$ifdef use_synapse} if content.Count > 0 then begin // Variable replacement parser.Content := content.Text; parser.Replace; content.Text .= parser.Content; content.SaveToStream(http.Document); end; if http.HTTPMethod(method, AURL) then begin writeln; writeln('Status: ', http.ResultCode); writeln; writeln('Headers:'); for s in http.Headers do writeln(' ', s); writeln; content.LoadFromStream(http.Document); writeln(content.Text); end else begin ExitCode := 2; writeln; writeln('FAILED! Last Socket Error: ', http.Sock.SocksLastError); end; {$endif} {$ifdef use_fclweb} response := TMemoryStream.Create; request := nil; if content.Count > 0 then begin request := TMemoryStream.Create; // Variable replacement parser.Content := content.Text; parser.Replace; content.Text := parser.Content; content.SaveToStream(request); request.Position := 0; http.RequestBody := request; end; try http.HTTPMethod(method, AURL, response, []); except on E: Exception do begin writeln; writeln('Failed! ', E.Message); Halt(1); end; end; writeln; writeln('Status: ', http.ResponseStatusCode, ' (', http.ResponseStatusText, ')'); writeln; writeln('Headers:'); for s in http.ResponseHeaders do writeln(' ', s); writeln; response.Position := 0; if beautify and (Pos('application/json', http.GetHeader(http.ResponseHeaders, 'Content-Type')) > 0) then begin jsonParser := TJSONParser.Create(response); jsonData := jsonParser.Parse; writeln(jsonData.FormatJSON); jsonData.Free; jsonParser.Free; end else begin content.LoadFromStream(response); writeln(content.Text); end; response.Free; request.Free; {$endif} end; procedure CmdBasicAuth(AData: String); var separator: Char; i: Integer; begin separator := AData[1]; i := 2; while (i < Length(AData)) and (AData[i] <> separator) do Inc(i); http.UserName := Copy(AData, 2, i - 2); http.Password := Copy(AData, i + 1, Length(AData)); end; function ProcessCommand(ALine: String): Boolean; begin Result := False; if AnsiStartsStr('Ask ', ALine) then begin Result := True; CmdAskUser(Copy(ALine, 5, Length(ALine))); end else if AnsiStartsStr('Header ', ALine) then begin Result := True; CmdHeader(Copy(ALine, 8, Length(ALine))); end else if AnsiStartsStr('Method ', ALine) then begin Result := True; method := Copy(ALine, 8, Length(ALine)); end else // We don't include the space here, since we also interpret this following // char as separator for username and password! (In case the username itself // contains a space.) if AnsiStartsStr('BasicAuth', ALine) then begin Result := True; CmdBasicAuth(Copy(ALine, 10, Length(ALine))); end else if ALine = 'Beautify' then begin Result := True; beautify := True; end else if AnsiStartsStr('Call ', ALine) then begin Result := True; url := Copy(ALine, 6, Length(ALine)); end; end; procedure ListProfiles; var sr: TSearchRec; begin Writeln('Known profiles:'); if FindFirst(templateDir + '*.rest', faAnyFile, sr) = 0 then begin repeat writeln(' ', Copy(sr.Name, 1, Length(sr.Name) - 5)); until FindNext(sr) <> 0; end; end; begin configDir := GetAppConfigDir(False); templateDir := configDir + 'templates' + PathDelim; templateFile := templateDir + ParamStr(1) + '.rest'; if ParamCount <> 1 then begin Writeln('Usage: ', ExtractFileName(ParamStr(0)), ' '); Writeln; ListProfiles; Halt(0); end; if FileExists(ParamStr(1)) then begin AssignFile(data, ParamStr(1)); templateName := ExtractFileName(ParamStr(1)); if AnsiEndsStr('.rest', templateName) then templateName := Copy(templateName, 1, Length(templateName) - 5); end else if FileExists(templateFile) then begin AssignFile(data, templateFile); templateName := ParamStr(1); end else begin writeln('Template not found!'); Halt(1); end; Reset(data); sessionIni := TIniFile.Create(configDir + 'session.ini'); parser := TJTemplateParser.Create; content := TStringList.Create; beautify := False; //By default, we don't want to manipulate output. {$ifdef use_synapse} http := THTTPSend.Create; {$endif} {$ifdef use_fclweb} http := TFPHttpClient.Create(nil); {$endif} commandMode := True; try while not EOF(data) do begin ReadLn(data, line); if commandMode and (line <> '') and not ProcessCommand(line) then commandMode := False; if not commandMode then content.Add(line); end; if url <> '' then ProcessCall(url); finally sessionIni.Free; parser.Free; http.Free; content.Free; CloseFile(data); end; end.