Teru Komaki's Blog (Temporary)

FileMakerでURLをパースするカスタム関数を作りました

AWSのSDKなどを使わずに、AWSのAPIを利用する際に、リクエストのヘッダーに署名を含める必要があります。

詳細は、以下のリンクを参照して頂きたいです。

AWS API リクエストの署名 - AWS 全般のリファレンス

AWS API リクエストの署名 - AWS 全般のリファレンス

海外のサンプルファイルを色々と見ましたが、やはり、自分で手を動かして、コードを書かないと理解できないので、ドキュメントを見て実装しました。

手が空いたら、会社のブログで、AWSのAPIを実行する方法については、記事を書きたいと思います…

更新履歴(2022–12–27)

会社のブログを更新しました。

FileMaker から S3 や EC2 などの AWS の API を利用する方法 | フルーデンス

FileMaker から S3 や EC2 などの AWS の API を利用する方法 | フルーデンス

更新履歴(2023–03–06)

カスタム関数にバグがあったので、修正しました。

上記のAWSのドキュメントの通りですが、AWSのAPI をリクエストする際に、hostとかパスとかクエリーが必要になります。

そのためにタイトルの通り、カスタム関数を作りました。

余談ですが…

カスタム関数を公開しましたら Nice!! とコメントを頂きました。

一言だとしても、コメント頂くと意外に嬉しいものですね。

私も、今後は Nice!! など気軽にコメントするように心がけます。

カスタム関数について

ParseUrl ( _url )

試したい方は、以下のURLを参照して、自分のカスタムAppに追加して頂ければと思います。

FileMaker Custom Function: ParseUrl ( _url )

FileMaker Custom Function: ParseUrl ( _url )

カスタム関数

 1/\* ---------------------------------------------------------------------------
 2ParseUrl ( \_url )
 3
 4Description:
 5Parse the URL and return the result as JSON.
 6
 7Note:
 8- If urlIsEmpty is 'false', the URL may have failed to parse.
 9- Please let me know if there is anything I have overlooked.
10- For the structure of the URL, I referred to the URL below.
11  https://en.wikipedia.org/wiki/URL
12
13Example:
14ParseUrl ( "https://username:[email protected]:80/dir1/file.txt?q1=v1&q2=v2#fragment" )
15-> {"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"}
16
17ParseUrl ( "https://en.wikipedia.org/wiki/URL" )
18-> {"fileName":"","fragment":"","host":"en.wikipedia.org","password":"","path":"/wiki/URL","port":"","query":"","scheme":"https","urlIsEmpty":true,"userName":""}
19
20History:
212022-11-24, Teruhiro Komaki <[email protected]>
22--------------------------------------------------------------------------- \*/
23
24Let ( \[
25// \_url = "https://username:[email protected]:80/dir1/file.txt?q1=v1&q2=v2#fragment" ;
26~url = \_url ;
27
28~scheme = GetValue ( Substitute ( ~url ; "://" ; "¶" ) ; 1 ) ;
29~url = Substitute ( ~url ; ~scheme & "://" ; "" ) ;
30
31~userinfo = If ( PatternCount ( ~url ; "@" ) ; GetValue ( Substitute ( ~url ; "@" ; "¶" ) ; 1 ) ) ;
32~userinfoList = Substitute ( ~userinfo ; ":" ; "¶" ) ;
33~userName = GetValue ( ~userinfoList ; 1 ) ;
34~password = GetValue ( ~userinfoList ; 2 ) ;
35~url = If ( not IsEmpty ( ~userinfo ) ; Substitute ( ~url ; ~userinfo & "@" ; "" ) ; ~url ) ;
36
37~host = GetValue ( Substitute ( ~url ; \[ ":" ; "¶" \] ; \[ "/" ; "¶" \] ; \[ "?" ; "¶" \] ; \[ "#" ; "¶" \] ) ; 1 ) ;
38~url = Substitute ( ~url ; ~host ; "" ) ;
39
40~port = GetAsNumber ( GetValue ( Substitute ( ~url ; \[ "/" ; "¶" \] ; \[ "?" ; "¶" \] ; \[ "#" ; "¶" \] ) ; 1 ) ) ;
41~url = If ( not IsEmpty ( ~port ) ; Substitute ( ~url ; ":" & ~port ; "" ) ; ~url ) ;
42
43~path = GetValue ( Substitute ( ~url ; \[ "?" ; "¶" \] ; \[ "#" ; "¶" \] ) ; 1 ) ;
44~url = If ( not IsEmpty ( ~path ) ; Substitute ( ~url ; ~path ; "" ) ; ~url ) ;
45
46~pathList = Substitute ( ~path ; "/" ; "¶" ) ;
47~pathListLast = GetValue ( ~pathList ; ValueCount ( ~pathList ) ) ;
48~fileName = If ( GetAsBoolean ( PatternCount ( ~pathListLast ; "." ) ) ; ~pathListLast ; "" ) ;
49
50~fragment = GetValue ( Substitute ( ~url ; \[ "#" ; "¶" \] ) ; 2 ) ;
51~url = If ( not IsEmpty ( ~fragment ) ; Substitute ( ~url ; "#" & ~fragment ; "" ) ; ~url ) ;
52
53~query = GetValue ( Substitute ( ~url ; \[ "?" ; "¶" \] ) ; 2 ) ;
54~url = If ( not IsEmpty ( ~query ) ; Substitute ( ~url ; "?" & ~query ; "" ) ; ~url ) ;
55
56~urlIsEmpty = If ( IsEmpty ( ~url ) ; True ; False )
57
58\] ;
59
60JSONSetElement ( "" ;
61\[ "scheme" ; ~scheme ; JSONString \] ;
62\[ "userName" ; ~userName ; JSONString \] ;
63\[ "password" ; ~password ; JSONString \] ;
64\[ "host" ; ~host ; JSONString \] ;
65\[ "port" ; ~port ; JSONString \] ;
66\[ "path" ; ~path ; JSONString \] ;
67\[ "fileName" ; ~fileName ; JSONString \] ;
68\[ "fragment" ; ~fragment ; JSONString \] ;
69\[ "query" ; ~query ; JSONString \] ;
70\[ "urlIsEmpty" ; ~urlIsEmpty ; JSONBoolean \]
71)
72
73) /\*Let\*/

コード(2023-03-06)

 1/\* ---------------------------------------------------------------------------
 2ParseUrl ( \_url )
 3
 4Description:
 5Parse the URL and return the result as JSON.
 6
 7Note:
 8- If urlIsEmpty is 'false', the URL may have failed to parse.
 9- Please let me know if there is anything I have overlooked.
10- For the structure of the URL, I referred to the URL below.
11  https://en.wikipedia.org/wiki/URL
12
13Example:
14ParseUrl ( "https://username:[email protected]:80/dir1/file.txt?q1=v1&q2=v2#fragment" )
15-> {"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"}
16
17ParseUrl ( "https://en.wikipedia.org/wiki/URL" )
18-> {"fileName":"","fragment":"","host":"en.wikipedia.org","password":"","path":"/wiki/URL","port":"","query":"","scheme":"https","urlIsEmpty":true,"userName":""}
19
20ParseUrl ( "https://username:[email protected]:80/path/to/file.txt?list-type=2&prefix=s3Prefix/a/b/#fragment" )
21-> {"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"}
22
23History:
242022-11-24, Teruhiro Komaki
25create.
262023-02-24, Teruhiro Komaki
27It was fixed because it did not consider the case where "/" was included in the query.
28--------------------------------------------------------------------------- \*/
29
30Let ( \[
31// \_url = "https://username:[email protected]:80/path/to/file.txt?list-type=2&prefix=s3Prefix/a/b/#fragment" ;
32~url = \_url ;
33~urlLength = Length ( ~url ) ;
34
35// scheme
36~scheme = GetValue ( Substitute ( ~url ; "://" ; "¶" ) ; 1 ) ;
37~schemeLength = Length ( ~scheme & "://" ) ;
38~url = Middle ( ~url ; ( ~schemeLength + 1 ) ; ~urlLength ) ;
39
40//userInfo
41~userinfo = If ( PatternCount ( ~url ; "@" ) ; GetValue ( Substitute ( ~url ; "@" ; "¶" ) ; 1 ) ) ; // username:password@
42~userinfoLength = Length ( ~userinfo & "@" ) ;
43~userinfoList = Substitute ( ~userinfo ; ":" ; "¶" ) ;
44~userName = GetValue ( ~userinfoList ; 1 ) ;
45~password = GetValue ( ~userinfoList ; 2 ) ;
46~url = If ( not IsEmpty ( ~userinfo ) ; Middle ( ~url ; ( ~userinfoLength + 1 ) ; ~urlLength ) ; ~url ) ;
47
48// host
49~host = GetValue ( Substitute ( ~url ; \[ ":" ; "¶" \] ; \[ "/" ; "¶" \] ; \[ "?" ; "¶" \] ; \[ "#" ; "¶" \] ) ; 1 ) ;
50~hostLength = Length ( ~host ) ;
51~url = Middle ( ~url ; ( ~hostLength + 1 ) ; ~urlLength ) ;
52
53// port
54~port = GetAsNumber ( GetValue ( Substitute ( ~url ; \[ "/" ; "¶" \] ; \[ "?" ; "¶" \] ; \[ "#" ; "¶" \] ) ; 1 ) ) ;
55~portLength = Length ( ":" & ~port ) ;
56~url = If ( not IsEmpty ( ~port ) ; Middle ( ~url ; ( ~portLength + 1 ) ; ~urlLength ) ; ~url ) ;
57
58// path
59~path = GetValue ( Substitute ( ~url ; \[ "?" ; "¶" \] ; \[ "#" ; "¶" \] ) ; 1 ) ;
60~pathLength = Length ( ~path ) ;
61~url = If ( not IsEmpty ( ~path ) ; Middle ( ~url ; ( ~pathLength + 1 ) ; ~urlLength ) ; ~url ) ;
62
63// file
64~pathList = Substitute ( ~path ; "/" ; "¶" ) ;
65~pathListLast = GetValue ( ~pathList ; ValueCount ( ~pathList ) ) ;
66~fileName = If ( GetAsBoolean ( PatternCount ( ~pathListLast ; "." ) ) ; ~pathListLast ; "" ) ;
67
68// query
69~isQuery = GetAsBoolean ( Left ( ~url ; 1 ) = "?" ) ;
70~query = GetValue ( Substitute ( ~url ; \[ "?" ; "" \] ; \[ "#" ; "¶" \] ) ; 1 ) ;
71~queryLength = Length ( "?" & ~query ) ;
72~url = If ( ~isQuery ; Middle ( ~url ; ( ~queryLength + 1 ) ; ~urlLength ) ; ~url ) ;
73
74// fragment
75~fragment = GetValue ( Substitute ( ~url ; \[ "#" ; "¶" \] ) ; 2 ) ;
76~fragmentLength = Length ( "#" & ~fragment ) ;
77~url = If ( not IsEmpty ( ~fragment ) ; Middle ( ~url ; ( ~fragmentLength + 1 ) ; ~urlLength ) ; ~url ) ;
78
79// check
80~urlIsEmpty = If ( IsEmpty ( ~url ) ; True ; False )
81
82\] ;
83
84JSONSetElement ( "" ;
85\[ "scheme" ; ~scheme ; JSONString \] ;
86\[ "userName" ; ~userName ; JSONString \] ;
87\[ "password" ; ~password ; JSONString \] ;
88\[ "host" ; ~host ; JSONString \] ;
89\[ "port" ; ~port ; JSONString \] ;
90\[ "path" ; ~path ; JSONString \] ;
91\[ "fileName" ; ~fileName ; JSONString \] ;
92\[ "fragment" ; ~fragment ; JSONString \] ;
93\[ "query" ; ~query ; JSONString \] ;
94\[ "urlIsEmpty" ; ~urlIsEmpty ; JSONBoolean \]
95)
96
97) /\*Let\*/

サンプル

1ParseUrl ( "https://username:[email protected]:80/dir1/file.txt?q1=v1&q2=v2#fragment" )
 1{
 2  "fileName": "file.txt",
 3  "fragment": "fragment",
 4  "host": "bucketname.s3.ap-northeast-1.amazonaws.com",
 5  "password": "password",
 6  "path": "/dir1/file.txt",
 7  "port": "999",
 8  "query": "q1=v1&q2=v2",
 9  "scheme": "https",
10  "urlIsEmpty": true,
11  "userName": "username"
12}
1ParseUrl ( "https://www.briandunning.com/cf/2627" )
 1{
 2  "fileName": "",
 3  "fragment": "",
 4  "host": "www.briandunning.com",
 5  "password": "",
 6  "path": "/cf/2627",
 7  "port": "",
 8  "query": "",
 9  "scheme": "https",
10  "urlIsEmpty": true,
11  "userName": ""
12}

バグなど見つかりましたら、コメント頂ければと思います。