Edited at

Cocoaの機能を使ってURLをGET/POSTするAppleScriptハンドラ

More than 1 year has passed since last update.


URLをGETするAppleScriptハンドラ


  • シェルでいうところのcurl 'http://www.example.com/'みたいなもの


GETRequestForURL.scpt

use scripting additions

use framework "Foundation"

set requestURL to current application's NSURL's URLWithString:"https://www.example.com/"

set response to my GETRequestForURL(requestURL)

set returnedString to current application's NSString's alloc()'s initWithData:(response's |data|) encoding:(current application's NSUTF8StringEncoding)
return returnedString as text

on GETRequestForURL(requestURL)
--require framework: Foundation
set session to my getValidURLSession()
set task to session's dataTaskWithURL:requestURL
task's resume()
return my fetchURLSesstionTasksResult(current application's NSArray's arrayWithObject:task)'s firstObject()
end GETRequestForURL

on getValidURLSession()
--require framework: Foundation
global URLSession
try
if URLSession = missing value then
error number -2753
end if
on error number -2753
set configuration to current application's NSURLSessionConfiguration's ephemeralSessionConfiguration()
set URLSession to current application's NSURLSession's sessionWithConfiguration:configuration delegate:(me) delegateQueue:(missing value)
end try
return URLSession
end getValidURLSession

on URLSession:session didBecomeInvalidWithError:anError
global URLSession
log "URLSession invalidated"
set URLSession to missing value
end URLSession:didBecomeInvalidWithError:

on fetchURLSesstionTasksResult(tasks)
my waitForCompletionOfURLSessionTasks(tasks)
my errorURLSessionTasksIfNeeded(tasks)
return my getResponsesToURLSessionTasks(tasks)
end fetchURLSesstionTasksResult

on waitForCompletionOfURLSessionTasks(tasks)
--require framework: Foundation
set tasksAreRunningPredicate to current application's NSPredicate's predicateWithFormat_("NONE state == %@", current application's NSURLSessionTaskStateRunning as integer)
repeat until tasksAreRunningPredicate's evaluateWithObject:tasks
delay 0.01
end repeat
end waitForCompletionOfURLSessionTasks

on errorURLSessionTasksIfNeeded(tasks)
--require framework: Foundation
repeat with errorTask in (tasks's filteredArrayUsingPredicate:(current application's NSPredicate's predicateWithFormat:"error != nil"))
error errorTask's |error|'s localizedDescription as text number errorTask's |error|'s code as integer
end repeat
repeat with notCompletedTask in (tasks's filteredArrayUsingPredicate:(current application's NSPredicate's predicateWithFormat_("state != %@", current application's NSURLSessionTaskStateCompleted as integer)))
error "task has not completed"
end repeat
end errorURLSessionTasksIfNeeded

on getResponsesToURLSessionTasks(tasks)
--require framework: Foundation
global responsesToURLSessionTask
try
responsesToURLSessionTask
on error number -2753
set responsesToURLSessionTask to current application's NSMutableArray's alloc()'s init()
end try
set newTasksFilterPredicate to current application's NSPredicate's predicateWithFormat_("NOT (taskIdentifier IN %@)", responsesToURLSessionTask's valueForKeyPath:"task.taskIdentifier")
repeat with newTask in (tasks's filteredArrayUsingPredicate:newTasksFilterPredicate)
(responsesToURLSessionTask's addObject:{task:newTask, |data|:current application's NSMutableData's alloc()'s init()})
end repeat
responsesToURLSessionTask's sortUsingDescriptors:{current application's NSSortDescriptor's sortDescriptorWithKey:"task.taskIdentifier" ascending:true}
set responsesFilterPredicate to current application's NSPredicate's predicateWithFormat_("task.taskIdentifier IN %@", tasks's valueForKey:"taskIdentifier")
return responsesToURLSessionTask's filteredArrayUsingPredicate:responsesFilterPredicate
end getResponsesToURLSessionTasks

on getResponseToURLSesstionTask(task)
--require framework: Foundation
return my getResponsesToURLSessionTasks(current application's NSArray's arrayWithObject:task)'s firstObject()
end getResponseToURLSesstionTask

on URLSession:session taskIsWaitingForConnectivity:task
log "waiting for connectivity..."
end URLSession:taskIsWaitingForConnectivity:

on URLSession:session task:task didSendBodyData:bytesSent totalBytesSent:totalBytesSent totalBytesExpectedToSend:totalBytesExpectedToSend
log "sending..."
end URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:

on URLSession:session dataTask:task didReceiveData:aData
log "receiving..."
set receivedData to my getResponseToURLSesstionTask(task)'s |data|
receivedData's appendData:aData
end URLSession:dataTask:didReceiveData:

on URLSession:session task:task didCompleteWithError:anError
log "URLSessionTask completed"
end URLSession:task:didCompleteWithError:



URLをPOSTするAppleScriptハンドラ


  • シェルでいうところのcurl -F 'name=value' 'http://www.example.com/'みたいなもの


POSTRequestForURL.scpt

use scripting additions

use framework "Foundation"

set requestURL to current application's NSURL's URLWithString:"https://www.example.com/"
set postString to current application's NSString's stringWithString:"name=value"
set allowedCharacters to current application's NSCharacterSet's URLQueryAllowedCharacterSet
set postData to (postString's stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters)'s dataUsingEncoding:(current application's NSUTF8StringEncoding)

set response to my POSTRequestForURL(requestURL, postData)

set returnedString to current application's NSString's alloc()'s initWithData:(response's |data|) encoding:(current application's NSUTF8StringEncoding)
return returnedString as text

on POSTRequestForURL(requestURL, dataToPost)
--require framework: Foundation
set request to current application's NSMutableURLRequest's requestWithURL:requestURL
set request's HTTPMethod to "POST"
request's setValue:"application/x-www-form-urlencoded" forHTTPHeaderField:"Content-Type"
set session to my getValidURLSession()
set task to session's uploadTaskWithRequest:request fromData:dataToPost
task's resume()
return my fetchURLSesstionTasksResult(current application's NSArray's arrayWithObject:task)'s firstObject()
end POSTRequestForURL

on getValidURLSession()
--require framework: Foundation
global URLSession
try
if URLSession = missing value then
error number -2753
end if
on error number -2753
set configuration to current application's NSURLSessionConfiguration's ephemeralSessionConfiguration()
set URLSession to current application's NSURLSession's sessionWithConfiguration:configuration delegate:(me) delegateQueue:(missing value)
end try
return URLSession
end getValidURLSession

on URLSession:session didBecomeInvalidWithError:anError
global URLSession
log "URLSession invalidated"
set URLSession to missing value
end URLSession:didBecomeInvalidWithError:

on fetchURLSesstionTasksResult(tasks)
my waitForCompletionOfURLSessionTasks(tasks)
my errorURLSessionTasksIfNeeded(tasks)
return my getResponsesToURLSessionTasks(tasks)
end fetchURLSesstionTasksResult

on waitForCompletionOfURLSessionTasks(tasks)
--require framework: Foundation
set tasksAreRunningPredicate to current application's NSPredicate's predicateWithFormat_("NONE state == %@", current application's NSURLSessionTaskStateRunning as integer)
repeat until tasksAreRunningPredicate's evaluateWithObject:tasks
delay 0.01
end repeat
end waitForCompletionOfURLSessionTasks

on errorURLSessionTasksIfNeeded(tasks)
--require framework: Foundation
repeat with errorTask in (tasks's filteredArrayUsingPredicate:(current application's NSPredicate's predicateWithFormat:"error != nil"))
error errorTask's |error|'s localizedDescription as text number errorTask's |error|'s code as integer
end repeat
repeat with notCompletedTask in (tasks's filteredArrayUsingPredicate:(current application's NSPredicate's predicateWithFormat_("state != %@", current application's NSURLSessionTaskStateCompleted as integer)))
error "task has not completed"
end repeat
end errorURLSessionTasksIfNeeded

on getResponsesToURLSessionTasks(tasks)
--require framework: Foundation
global responsesToURLSessionTask
try
responsesToURLSessionTask
on error number -2753
set responsesToURLSessionTask to current application's NSMutableArray's alloc()'s init()
end try
set newTasksFilterPredicate to current application's NSPredicate's predicateWithFormat_("NOT (taskIdentifier IN %@)", responsesToURLSessionTask's valueForKeyPath:"task.taskIdentifier")
repeat with newTask in (tasks's filteredArrayUsingPredicate:newTasksFilterPredicate)
(responsesToURLSessionTask's addObject:{task:newTask, |data|:current application's NSMutableData's alloc()'s init()})
end repeat
responsesToURLSessionTask's sortUsingDescriptors:{current application's NSSortDescriptor's sortDescriptorWithKey:"task.taskIdentifier" ascending:true}
set responsesFilterPredicate to current application's NSPredicate's predicateWithFormat_("task.taskIdentifier IN %@", tasks's valueForKey:"taskIdentifier")
return responsesToURLSessionTask's filteredArrayUsingPredicate:responsesFilterPredicate
end getResponsesToURLSessionTasks

on getResponseToURLSesstionTask(task)
--require framework: Foundation
return my getResponsesToURLSessionTasks(current application's NSArray's arrayWithObject:task)'s firstObject()
end getResponseToURLSesstionTask

on URLSession:session taskIsWaitingForConnectivity:task
log "waiting for connectivity..."
end URLSession:taskIsWaitingForConnectivity:

on URLSession:session task:task didSendBodyData:bytesSent totalBytesSent:totalBytesSent totalBytesExpectedToSend:totalBytesExpectedToSend
log "sending..."
end URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:

on URLSession:session dataTask:task didReceiveData:aData
log "receiving..."
set receivedData to my getResponseToURLSesstionTask(task)'s |data|
receivedData's appendData:aData
end URLSession:dataTask:didReceiveData:

on URLSession:session task:task didCompleteWithError:anError
log "URLSessionTask completed"
end URLSession:task:didCompleteWithError:



複数のURLを並列でGETするAppleScriptハンドラ


parallelGETRequestForURLs.scpt

use scripting additions

use framework "Foundation"

set requestURLs to {current application's NSURL's URLWithString:"https://www.example.com/", current application's NSURL's URLWithString:"https://www.apple.com", current application's NSURL's URLWithString:"https://www.yahoo.co.jp"}

set responses to my parallelGETRequestForURLs(requestURLs)

repeat with response in responses
set returnedString to (current application's NSString's alloc()'s initWithData:(response's |data|) encoding:(current application's NSUTF8StringEncoding))
log returnedString as text
end repeat

on parallelGETRequestForURLs(requestURLs)
--require framework: Foundation
set session to my getValidURLSession()
set tasks to current application's NSMutableArray's alloc()'s init()
repeat with requestURL in requestURLs
set task to (session's dataTaskWithURL:requestURL)
task's resume()
(tasks's addObject:task)
end repeat
return my fetchURLSesstionTasksResult(tasks)
end parallelGETRequestForURLs

on getValidURLSession()
--require framework: Foundation
global URLSession
try
if URLSession = missing value then
error number -2753
end if
on error number -2753
set configuration to current application's NSURLSessionConfiguration's ephemeralSessionConfiguration()
set URLSession to current application's NSURLSession's sessionWithConfiguration:configuration delegate:(me) delegateQueue:(missing value)
end try
return URLSession
end getValidURLSession

on URLSession:session didBecomeInvalidWithError:anError
global URLSession
log "URLSession invalidated"
set URLSession to missing value
end URLSession:didBecomeInvalidWithError:

on fetchURLSesstionTasksResult(tasks)
my waitForCompletionOfURLSessionTasks(tasks)
my errorURLSessionTasksIfNeeded(tasks)
return my getResponsesToURLSessionTasks(tasks)
end fetchURLSesstionTasksResult

on waitForCompletionOfURLSessionTasks(tasks)
--require framework: Foundation
set tasksAreRunningPredicate to current application's NSPredicate's predicateWithFormat_("NONE state == %@", current application's NSURLSessionTaskStateRunning as integer)
repeat until tasksAreRunningPredicate's evaluateWithObject:tasks
delay 0.01
end repeat
end waitForCompletionOfURLSessionTasks

on errorURLSessionTasksIfNeeded(tasks)
--require framework: Foundation
repeat with errorTask in (tasks's filteredArrayUsingPredicate:(current application's NSPredicate's predicateWithFormat:"error != nil"))
error errorTask's |error|'s localizedDescription as text number errorTask's |error|'s code as integer
end repeat
repeat with notCompletedTask in (tasks's filteredArrayUsingPredicate:(current application's NSPredicate's predicateWithFormat_("state != %@", current application's NSURLSessionTaskStateCompleted as integer)))
error "task has not completed"
end repeat
end errorURLSessionTasksIfNeeded

on getResponsesToURLSessionTasks(tasks)
--require framework: Foundation
global responsesToURLSessionTask
try
responsesToURLSessionTask
on error number -2753
set responsesToURLSessionTask to current application's NSMutableArray's alloc()'s init()
end try
set newTasksFilterPredicate to current application's NSPredicate's predicateWithFormat_("NOT (taskIdentifier IN %@)", responsesToURLSessionTask's valueForKeyPath:"task.taskIdentifier")
repeat with newTask in (tasks's filteredArrayUsingPredicate:newTasksFilterPredicate)
(responsesToURLSessionTask's addObject:{task:newTask, |data|:current application's NSMutableData's alloc()'s init()})
end repeat
responsesToURLSessionTask's sortUsingDescriptors:{current application's NSSortDescriptor's sortDescriptorWithKey:"task.taskIdentifier" ascending:true}
set responsesFilterPredicate to current application's NSPredicate's predicateWithFormat_("task.taskIdentifier IN %@", tasks's valueForKey:"taskIdentifier")
return responsesToURLSessionTask's filteredArrayUsingPredicate:responsesFilterPredicate
end getResponsesToURLSessionTasks

on getResponseToURLSesstionTask(task)
--require framework: Foundation
return my getResponsesToURLSessionTasks(current application's NSArray's arrayWithObject:task)'s firstObject()
end getResponseToURLSesstionTask

on URLSession:session taskIsWaitingForConnectivity:task
log "waiting for connectivity..."
end URLSession:taskIsWaitingForConnectivity:

on URLSession:session task:task didSendBodyData:bytesSent totalBytesSent:totalBytesSent totalBytesExpectedToSend:totalBytesExpectedToSend
log "sending..."
end URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:

on URLSession:session dataTask:task didReceiveData:aData
log "receiving..."
set receivedData to my getResponseToURLSesstionTask(task)'s |data|
receivedData's appendData:aData
end URLSession:dataTask:didReceiveData:

on URLSession:session task:task didCompleteWithError:anError
log "URLSessionTask completed"
end URLSession:task:didCompleteWithError:



更新履歴


  • 2018-07-20: FoundationフレームワークのNSURLSessionクラスを使って作成

  • 2018-07-21: エラー対応機能を追加

  • 2018-08-17: POSTRequestForURLハンドラを作成

  • 2018-08-18: NSURLSessionConfigurationを、キャッシュやcookieを使用しないephemeralSessionConfigurationに変更

  • 2018-09-05: invalidateされたURLSessionを避けるためにgetValidURLSessionハンドラを作成

  • 2018-09-06: getResponsesToURLSessionTasksハンドラを作成して並列実行に対応

  • 2018-09-10: 並列にGETリクエストを実行するparallelGETRequestForURLsハンドラを作成