FileMakerでURLをパースするカスタム関数を作りました
2023年01月06日 金曜日 09時00分AWSのSDKなどを使わずに、AWSのAPIを利用する際に、リクエストのヘッダーに署名を含める必要があります。
詳細は、以下のリンクを参照して頂きたいです。
AWS API リクエストの署名 - AWS 全般のリファレンス

海外のサンプルファイルを色々と見ましたが、やはり、自分で手を動かして、コードを書かないと理解できないので、ドキュメントを見て実装しました。
手が空いたら、会社のブログで、AWSのAPIを実行する方法については、記事を書きたいと思います…
...
更新履歴(2022–12–27)
会社のブログを更新しました。
FileMaker から S3 や EC2 などの AWS の API を利用する方法 | フルーデンス

...
更新履歴(2023–03–06)
カスタム関数にバグがあったので、修正しました。
...
上記のAWSのドキュメントの通りですが、AWSのAPI をリクエストする際に、hostとかパスとかクエリーが必要になります。
そのためにタイトルの通り、カスタム関数を作りました。
余談ですが…
カスタム関数を公開しましたら Nice!! とコメントを頂きました。
一言だとしても、コメント頂くと意外に嬉しいものですね。
私も、今後は Nice!! など気軽にコメントするように心がけます。
カスタム関数について
ParseUrl ( _url )
試したい方は、以下のURLを参照して、自分のカスタムAppに追加して頂ければと思います。
FileMaker Custom Function: ParseUrl ( _url )

カスタム関数
/* ---------------------------------------------------------------------------
ParseUrl ( _url )
Description:
Parse the URL and return the result as JSON.
Note:
- If urlIsEmpty is 'false', the URL may have failed to parse.
- Please let me know if there is anything I have overlooked.
- For the structure of the URL, I referred to the URL below.
https://en.wikipedia.org/wiki/URL
Example:
ParseUrl ( "https://username:[email protected]:80/dir1/file.txt?q1=v1&q2=v2#fragment" )
-> {"fileName":"file.txt","fragment":"fragment","host":"bucketname.s3.ap-northeast-1.amazonaws.com","password":"password","path":"/dir1/file.txt","port":"80","query":"q1=v1&q2=v2","scheme":"https","urlIsEmpty":true,"userName":"username"}
ParseUrl ( "https://en.wikipedia.org/wiki/URL" )
-> {"fileName":"","fragment":"","host":"en.wikipedia.org","password":"","path":"/wiki/URL","port":"","query":"","scheme":"https","urlIsEmpty":true,"userName":""}
ParseUrl ( "https://username:[email protected]:80/path/to/file.txt?list-type=2&prefix=s3Prefix/a/b/#fragment" )
-> {"fileName":"file.txt","fragment":"fragment","host":"bucket-demo.s3.us-east-1.amazonaws.com","password":"password","path":"/path/to/file.txt","port":"80","query":"list-type=2&prefix=s3Prefix/a/b/","scheme":"https","urlIsEmpty":true,"userName":"username"}
History:
2022-11-24, Teruhiro Komaki
create.
2023-02-24, Teruhiro Komaki
It was fixed because it did not consider the case where "/" was included in the query.
--------------------------------------------------------------------------- */
Let ( [
// _url = "https://username:[email protected]:80/path/to/file.txt?list-type=2&prefix=s3Prefix/a/b/#fragment" ;
~url = _url ;
~urlLength = Length ( ~url ) ;
// scheme
~scheme = GetValue ( Substitute ( ~url ; "://" ; "¶" ) ; 1 ) ;
~schemeLength = Length ( ~scheme & "://" ) ;
~url = Middle ( ~url ; ( ~schemeLength + 1 ) ; ~urlLength ) ;
//userInfo
~userinfo = If ( PatternCount ( ~url ; "@" ) ; GetValue ( Substitute ( ~url ; "@" ; "¶" ) ; 1 ) ) ; // username:password@
~userinfoLength = Length ( ~userinfo & "@" ) ;
~userinfoList = Substitute ( ~userinfo ; ":" ; "¶" ) ;
~userName = GetValue ( ~userinfoList ; 1 ) ;
~password = GetValue ( ~userinfoList ; 2 ) ;
~url = If ( not IsEmpty ( ~userinfo ) ; Middle ( ~url ; ( ~userinfoLength + 1 ) ; ~urlLength ) ; ~url ) ;
// host
~host = GetValue ( Substitute ( ~url ; [ ":" ; "¶" ] ; [ "/" ; "¶" ] ; [ "?" ; "¶" ] ; [ "#" ; "¶" ] ) ; 1 ) ;
~hostLength = Length ( ~host ) ;
~url = Middle ( ~url ; ( ~hostLength + 1 ) ; ~urlLength ) ;
// port
~port = GetAsNumber ( GetValue ( Substitute ( ~url ; [ "/" ; "¶" ] ; [ "?" ; "¶" ] ; [ "#" ; "¶" ] ) ; 1 ) ) ;
~portLength = Length ( ":" & ~port ) ;
~url = If ( not IsEmpty ( ~port ) ; Middle ( ~url ; ( ~portLength + 1 ) ; ~urlLength ) ; ~url ) ;
// path
~path = GetValue ( Substitute ( ~url ; [ "?" ; "¶" ] ; [ "#" ; "¶" ] ) ; 1 ) ;
~pathLength = Length ( ~path ) ;
~url = If ( not IsEmpty ( ~path ) ; Middle ( ~url ; ( ~pathLength + 1 ) ; ~urlLength ) ; ~url ) ;
// file
~pathList = Substitute ( ~path ; "/" ; "¶" ) ;
~pathListLast = GetValue ( ~pathList ; ValueCount ( ~pathList ) ) ;
~fileName = If ( GetAsBoolean ( PatternCount ( ~pathListLast ; "." ) ) ; ~pathListLast ; "" ) ;
// query
~isQuery = GetAsBoolean ( Left ( ~url ; 1 ) = "?" ) ;
~query = GetValue ( Substitute ( ~url ; [ "?" ; "" ] ; [ "#" ; "¶" ] ) ; 1 ) ;
~queryLength = Length ( "?" & ~query ) ;
~url = If ( ~isQuery ; Middle ( ~url ; ( ~queryLength + 1 ) ; ~urlLength ) ; ~url ) ;
// fragment
~fragment = GetValue ( Substitute ( ~url ; [ "#" ; "¶" ] ) ; 2 ) ;
~fragmentLength = Length ( "#" & ~fragment ) ;
~url = If ( not IsEmpty ( ~fragment ) ; Middle ( ~url ; ( ~fragmentLength + 1 ) ; ~urlLength ) ; ~url ) ;
// check
~urlIsEmpty = If ( IsEmpty ( ~url ) ; True ; False )
] ;
JSONSetElement ( "" ;
[ "scheme" ; ~scheme ; JSONString ] ;
[ "userName" ; ~userName ; JSONString ] ;
[ "password" ; ~password ; JSONString ] ;
[ "host" ; ~host ; JSONString ] ;
[ "port" ; ~port ; JSONString ] ;
[ "path" ; ~path ; JSONString ] ;
[ "fileName" ; ~fileName ; JSONString ] ;
[ "fragment" ; ~fragment ; JSONString ] ;
[ "query" ; ~query ; JSONString ] ;
[ "urlIsEmpty" ; ~urlIsEmpty ; JSONBoolean ]
)
) /*Let*/
サンプル
ParseUrl ( "https://username:[email protected]:80/dir1/file.txt?q1=v1&q2=v2#fragment" )
{
"fileName": "file.txt",
"fragment": "fragment",
"host": "bucketname.s3.ap-northeast-1.amazonaws.com",
"password": "password",
"path": "/dir1/file.txt",
"port": "999",
"query": "q1=v1&q2=v2",
"scheme": "https",
"urlIsEmpty": true,
"userName": "username"
}
ParseUrl ( "https://www.briandunning.com/cf/2627" )
{
"fileName": "",
"fragment": "",
"host": "www.briandunning.com",
"password": "",
"path": "/cf/2627",
"port": "",
"query": "",
"scheme": "https",
"urlIsEmpty": true,
"userName": ""
}
バグなど見つかりましたら、コメント頂ければと思います。