POST request using F# - https

I want to make a POST request with a body containing a simple key value pair
like { "Id":"VVE87BDA-B0A1-48F3-A7C7-F3482CE2UIJ" }
How can I do this in F# ??

Have a look at FSharp.Data library
Http.RequestString
( "http://httpbin.org/post",
headers = [ ContentType HttpContentTypes.Json ],
body = TextRequest """ {"test": 42} """)

You can also do this through .NET libraries like in C# or VB. Here's how it works with HttpWebRequest (assuming you aren't using task or async):
let obj = {| Id = "VVE87BDA-B0A1-48F3-A7C7-F3482CE2UIJ" |}
let req = WebRequest.CreateHttp "http://www.example.com"
req.Method <- "POST"
req.ContentType <- "application/json"
do (
use reqStream = req.GetRequestStream()
use sw = new StreamWriter(reqStream )
obj |> JsonConvert.SerializeObject |> sw.Write
)
use resp = req.GetResponse()
use respStream = resp.GetResponseStream()
use sr = new StreamReader(respStream)
let respBody = sr.ReadToEnd()
printfn "%s" respBody
async version:
let obj = {| Id = "VVE87BDA-B0A1-48F3-A7C7-F3482CE2UIJ" |}
let req = WebRequest.CreateHttp "http://www.example.com"
req.Method <- "POST"
req.ContentType <- "application/json"
do! async {
use! reqStream = req.GetRequestStreamAsync() |> Async.AwaitTask
use sw = new StreamWriter(reqStream )
do! obj |> JsonConvert.SerializeObject |> sw.WriteAsync |> Async.AwaitTask
}
use! resp = req.AsyncGetResponse()
use respStream = resp.GetResponseStream()
use sr = new StreamReader(respStream)
let! respBody = sr.ReadToEndAsync() |> Async.AwaitTask
printfn "%s" respBody
In either case it's best to make sure reqStream goes out of scope and gets disposed before the GetResponse call, to make sure the request data gets fully written.

Related

Swift- Use of unresolved identifier

I have the following Swift code where I am sending a POST request to a webserver and receiving a value back. The error that I receive is on the second to last line saying "Use of unresolved identifier"
func download_request() -> String {
let url:NSURL = NSURL(string: "http://url.com/read.php")!
let session = NSURLSession.sharedSession()
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringCacheData
let paramString = "data=name"
request.HTTPBody = paramString.dataUsingEncoding(NSUTF8StringEncoding)
let task = session.downloadTaskWithRequest(request) {
(let location, let response, let error) in
guard let _:NSURL = location, let _:NSURLResponse = response where error == nil else {
print("Error")
return
}
let urlContents = try! NSString(contentsOfURL: location!, encoding: NSUTF8StringEncoding)
guard let _:NSString = urlContents else {
print("Error")
return
}
}
task.resume()
return urlContents
}
How would I fix this error? I think that it means that I cannot use urlContents outside of the let task = session.downloadTaskWithRequest(request) { } but how would I declare the variable so that I can use it outside?
Try declaring urlContents outside of the session.downloadTaskWithRequest(request) { } block. Like so:
func download_request() -> String? {
let url:NSURL = NSURL(string: "http://url.com/read.php")!
let session = NSURLSession.sharedSession()
var urlContents: NSString?
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringCacheData
let paramString = "data=name"
request.HTTPBody = paramString.dataUsingEncoding(NSUTF8StringEncoding)
let task = session.downloadTaskWithRequest(request) {
(let location, let response, let error) in
guard let _:NSURL = location, let _:NSURLResponse = response where error == nil else {
print("Error")
return
}
urlContents = try? NSString(contentsOfURL: location!, encoding: NSUTF8StringEncoding)
guard let _:NSString = urlContents else {
print("Error")
return
}
}
task.resume()
return (urlContents as! String)
}
Then when you need to use urlContents unwrap it with an if let binding
if let contents = download_request() {
//Use safely unwrapped contents
}
You could make return type optional like below
func download_request() -> String? {
var urlContents: String?
....
....
let task = session.downloadTaskWithRequest(request) {
(let location, let response, let error) in
...
...
...
guard let _:NSURL = location, let _:NSURLResponse = response where error == nil else {
print("Error")
return
}
urlContents = try! NSString(contentsOfURL: location!, encoding: NSUTF8StringEncoding) as String
guard let _:NSString = urlContents else {
print("Error")
return
}
}
task.resume()
return urlContents
}
And call the method like
if let request = download_request() {
//do anything with your request
}
Suggesting you to rename your method properly since you are returning the downloaded data not the request.
And this is not the correct way to get your downloaded data back as a return to the method since the completionHandler will be called once the operation is done so urlContents will be nil. Hence create another method which takes String as input and call it within the completionHandler of downloadTaskWithRequest

Grails controller: how render image from byte array

I have byte array byteImg but I want render in my controller jpeg from byte array:
def getSelfie = new HTTPBuilder()
getSelfie.request(fullSelfieUrl, GET, JSON) { req ->
headers.'X-DreamFactory-Session-Token' = session_id
headers.'X-DreamFactory-Application-Name' = 'checkReg'
response.success = { resp, reader ->
assert resp.statusLine.statusCode == 200
println "Get response: ${resp.statusLine}"
println "Content-Type: ${resp.headers.'Content-Type'}"
resp = reader as grails.converters.JSON
String str = resp.toString()
JSONObject jsonObject = new JSONObject(str)
selfieRend = jsonObject.getString("selfie")
byteImg = selfieRend.getBytes()
render byteImg
return byteImg
}
response.'404' = {
println 'Information not found'
}
}
how to do it? Thank you so much
I haven't tested it but as per wiki this should work:
def getSelfie(){
def http = new AsyncHTTPBuilder(
poolSize : 4,
uri : fullSelfieUrl,
contentType : ContentType.JSON )
def result = http.get() { resp, json -> json.selfie.bytes }
while( !result.done ) Thread.sleep 1000
def bytes = result.get()
response.setHeader 'Content-disposition', "inline; filename=someName.jpg"
response.setHeader 'Content-Type', 'image/jpg'
response.outputStream.withStream{ it << bytes }
}

Digest function equivalent in Swift

I am attempting to write an authenticator app where I use SHA512 and 256 to encrypt some data and then display a number from the processed hashes. I have basically everything figured out and working except for the .digest function. I know how to do it in ruby, given below, but I can't figure out how to get it in iOS.
ruby:
def reset_secret
d = OpenSSL::Digest::SHA512.new
d << reset_sysid
d << 'AAaaAAAaaaAAA'
end
def reset_input(t)
[reset_sysid, email, t].join('|')
end
def reset_hmac(t)
hmac = OpenSSL::Digest::SHA256.new
hmac << reset_secret.digest
hmac << reset_input(t)
hmac.digest
OpenSSL::Digest::SHA256.new(hmac.digest).digest
end
Swift as of now:
func reset_secret()->String {
return (sysid+"AAaaAAAaaaAAA").sha512()
}
func reset_input(t:Int)->String{
var time:String = String(t)
var input:[String] = [sysid, email, time]
var stringrep:String = "|".join(input)
return stringrep
}
func reset_hmac(t:Int)->String{
var firstTime:String = (reset_secret() + reset_input(t)).sha256()
return firstTime
}
extension String {
func sha256() -> String {
let data = self.dataUsingEncoding(NSUTF8StringEncoding)!
var digest = [UInt8](count:Int(CC_SHA512_DIGEST_LENGTH), repeatedValue: 0)
CC_SHA512(data.bytes, CC_LONG(data.length), &digest)
let hexBytes = digest.map { String(format: "%02hhx", $0) }
return "".join(hexBytes)
}
func sha512() -> String {
let data = self.dataUsingEncoding(NSUTF8StringEncoding)!
var digest = [UInt8](count:Int(CC_SHA512_DIGEST_LENGTH), repeatedValue: 0)
CC_SHA512(data.bytes, CC_LONG(data.length), &digest)
let hexBytes = digest.map { String(format: "%02hhx", $0) }
return "".join(hexBytes)
}
To start, I need to get a .digest of the reset_secret() in reset_hmac(), but I haven't seemed to find an equivalent to this in swift

Cannot invoke initialiser for type 'JSON' with an argument list of type (data: NSUrlConnection?)

I am getting this error:
Cannot invoke initialiser for type 'JSON' with an argument list of type (data: NSUrlConnection?)
When I try to execute this code:
var url = NSURL(string: "http://****")
var request = NSMutableURLRequest(URL: url!, cachePolicy: NSURLRequestCachePolicy.ReturnCacheDataElseLoad, timeoutInterval: Double.infinity);
if IJReachability.isConnectedToNetwork(){
request = NSMutableURLRequest(URL: url!, cachePolicy: NSURLRequestCachePolicy.UseProtocolCachePolicy, timeoutInterval: Double.infinity);
}
var response: NSURLResponse?
let data = NSURLConnection?
do {
data = try NSURLConnection.sendSynchronousRequest(request, returningResponse: &response)
} catch (let e) {
print(e)
}
if data != nil {
var dataArray = JSON(data: data)
let dutch_sentence = dataArray[id]["dutch_sentence"]
let polish_sentence = dataArray[id]["polish_sentence"]
let navigationTitle = dutch_sentence.string!.uppercaseString
self.title = navigationTitle
//Populate labels
dutchSentenceLabel.text = dutch_sentence.string!
polishSentenceLabel.text = polish_sentence.string!
}
I am new to Swift and I am trying to fix the errors out of my code since it is updated but I am having a hard time on it since I am not experienced with the language.. can someone please help me out? I wouldn't be surprised if I messed up the whole code already actually..
I also tried this:
let url = NSURL(string: "http://****")
var request = NSMutableURLRequest(URL: url!, cachePolicy: NSURLRequestCachePolicy.ReturnCacheDataElseLoad, timeoutInterval: Double.infinity);
if IJReachability.isConnectedToNetwork(){
request = NSMutableURLRequest(URL: url!, cachePolicy: NSURLRequestCachePolicy.UseProtocolCachePolicy, timeoutInterval: Double.infinity);
}
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { (data, response, error) -> Void in
var dataArray = JSON(data: data!)
let dutch_sentence = dataArray[self.id]["dutch_sentence"]
let polish_sentence = dataArray[self.id]["polish_sentence"]
let navigationTitle = dutch_sentence.string!.uppercaseString
self.title = navigationTitle
//Populate labels
self.dutchSentenceLabel.text = dutch_sentence.string!
self.polishSentenceLabel.text = polish_sentence.string!
}
task.resume()
It has no errors but I don't know if it is the correct way and if it will work. I have to replace it on a lot of places so I want to be sure about if it works before I do that.
I believe you were intending to use JSONObjectWithData:options:error
Unless you were doing this using SwiftyJSON. If so, here is an excellent article detailing how to install and use it.

Returning from a function in a closure

I need to get an array of events for a certain day in Swift. Because EKEventStore.requestAccessToEntityType is run asynchronously, I am using dispatch_group_notify to wait for the completion handler of EKEventStore.requestAccessToEntityType to complete so I can do something with it then return it. But I can't return from the function inside the closure I pass to dispatch_group_notify because it tries the return from the closure, not the function. Here is my code
class func eventsOn(date: NSDate) -> [Event] {
var events = [Event]()
var ekEvents = [EKEvent]()
var dispatch_group = dispatch_group_create()
dispatch_group_enter(dispatch_group)
Event.eventStore.requestAccessToEntityType(EKEntityTypeEvent, completion: {
gotAccess, error in
let cal = NSCalendar.currentCalendar()
var comps = cal.components(.CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitDay, fromDate: date)
let aFewHoursAgo = NSDateComponents()
aFewHoursAgo.hour = -5
var daStartDate = cal.dateFromComponents(comps)!
daStartDate = cal.dateByAddingComponents(aFewHoursAgo, toDate: daStartDate, options: .allZeros)!
var aDay = NSDateComponents()
aDay.day = 1
var daEndDate = cal.dateByAddingComponents(aDay, toDate: daStartDate, options: .allZeros)!
daEndDate = daEndDate.dateByAddingTimeInterval(-1)!
let p = Event.eventStore.predicateForEventsWithStartDate(daStartDate, endDate: daEndDate, calendars: [Event.eventStore.defaultCalendarForNewEvents])
let tmp = Event.eventStore.eventsMatchingPredicate(p) as [EKEvent]?
if let _ = tmp {
ekEvents = tmp!
}
dispatch_group_leave(dispatch_group)
})
let queue = dispatch_get_global_queue(Int(QOS_CLASS_USER_INITIATED.value), 0)
dispatch_group_notify(dispatch_group, queue) {
println(ekEvents)
let ekEventId = Expression<String>("ekEventId")
let eventId = Expression<Int>("id")
for ekEvent in ekEvents {
let daEventId = Event.db["events"].filter(ekEventId == ekEvent.eventIdentifier).select(eventId).first![eventId]
events.append(Event.eventWithId(daEventId)!)
}
return events
}
}
So where I put return events inside of the block I passed to dispatch_group_notify it tries to return from the closure, but I'd like to return from the function. How can I do this?

Resources