F#: System.Net.WebException - exception

I am new to programming and F# is my first language. I am currently still very unfamiliar with .NET APIs.
As a beginner's project, I want to scrape a website. I want to write a function that, given a specific URL, automatically downloads all the HTML contents on that page. However, if the URL is invalid, rather than throwing a System.Net.WebException message, I want to return the Boolean output "False" instead.
Here is the relevant part of my code:
let noSuchURL (url: string) =
let html = downloadHtmlFromUrl url
let regexPattern = #"<title>Page not found</title>"
let matchResult = Regex.IsMatch(html, regexPattern)
matchResult
(I have tested the downloadHtmlFromUrl function in F# interactive, and it works fine.)
I realised that the code above does not return a Boolean value in the event that the address is invalid. Instead, System.Net.WebException is thrown, with the message "System.Net.WebException: The remote server returned an error: (404) Not Found".
What changes can I make to get a Boolean output?

Maybe catch the exception?
let noSuchURL (url: string) =
try
let html = downloadHtmlFromUrl url
let regexPattern = #"<title>Page not found</title>"
let matchResult = Regex.IsMatch(html, regexPattern)
matchResult
with :? System.Net.WebException -> false
One caveat: this program will return false if there is a WebException, no matter for what reason that exception being raised. If you want specifically to return false on 404 responses, you'll have to look closer at the WebException:
let noSuchURL (url: string) =
try
let html = downloadHtmlFromUrl url
let regexPattern = #"<title>Page not found</title>"
let matchResult = Regex.IsMatch(html, regexPattern)
matchResult
with
:? System.Net.WebException as e
when e.Status = WebExceptionStatus.ProtocolError ||
e.Status = WebExceptionStatus.NameResolutionFailure
-> false
For more on exceptions in F#, take a look at https://msdn.microsoft.com/en-us/library/dd233194.aspx.

Related

Alamofire string parameter hardcoded works but passing as string parameter does not

I'm attempting to make a Alamofire service call to retrieve a list of items in JSON. The issue I am having is that anytime I type in a special character: such as ' it somewhere resolves the string a unicode string while sending the request. When I type in o'sheas its coming back that I'm searching O\U2019sheas
func sendGetRequest(passedInString: String) {
PARAMETERS["searchTxt"] = passedInString
Alamofire.request(URL, method: .get , parameters: PARAMETERS, headers: HEADER)
.validate(statusCode: 200..<400)
.responseJSON { response in
debugPrint(response.request!)
switch response.result {
// GETTING NO RESULTS BECAUSE THE REQUEST IS TURNING the o'sheas into O\U2019sheas
But the odd thing is, if I just replace this:
PARAMETERS["searchTxt"] = passedInString
with a hardcoded string (the one I'm typing initially and getting no results)
PARAMETERS["searchTxt"] = "o'sheas"
...it works just fine and does not convert this to O\U2019sheas. Any idea how to fix this, and more importantly, why this is happening when passed in as a String parameter as opposed to hard coded string?
UPDATE:
I've tried adding the URLEncoding.default as the encoding parameter, same results.
I've also tried creating a Swift String Extension to be used on the searchTxt as passing it as parameter like so:
PARAMETERS["searchTxt"] = passedInString.escapeSpecialCharacters()
extension String {
mutating func escapeSpecialCharacters() {
// 1. Define replacements
let replacementCharacters = ["'" : "\'"]
// 2. Cycle through each replacement defined in the replacementCharacters array and remodify the string accordingly.
replacementCharacters.keys.forEach {
// 3. Replacing self with new modified string
self = self.replacingOccurrences(of: $0, with: replacementCharacters[$0]!)
}
}
}
But same results.
If you are sure about this Unicode problem, then you can use Encoder and Decoder functionality to handle this.
Or if you know the your String always will be same, then use Regex expression to append '\'
I think the problem is with the "get" - cause it will use your string in the URL as parameter, the "'" can't be handelt so well.
Try to create a url with URLComponents
var urlComponents = URLComponents()
urlComponents.scheme = scheme
urlComponents.host = host
urlComponents.path = path
urlComponents.queryItems = [queryItem]
then use urlComponents.url in
Alamofire.request(urlComponents.url, method: .get, headers: HEADERS) {...}
URLQueryItem(name: "Param", value: "eter")
Try below lines of code. May help you.
originalString = "o'sheas"
var escapedString = originalString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
PARAMETERS["searchTxt"] = escapedString

Dynamic Function Call in FSharp

Is it possible to take an FSharp function and convert it to a Dynamic function, alternatively is something like this coming to FSharp in the future?
let func (a:int) (b:int) : int =
a + b
let dynamicFunc = FSharpFunc.ToDynamicFunc(func)
let argumentList = [1; 2]
let object = dynamicFunc argumentList
let result = object :?> int
It appears that you currently have to fall back to standard reflection (like this: calling a F# function by name) however, this approach seems very brittle. Mainly because there's no real guarantee it works, and you have to know what's going on under the covers.
Something like this could be used to wrap any function and do things dynamically.
let wrapFun (x:'f) : 'f =
let args = FSharp.Reflection.FSharpType.GetFunctionElements <| x.GetType()
let runner (any:obj list) : obj =
// Do extra things
FSharpFunc.DynamicInvoke x
FSharp.Reflection.FSharpValue.MakeFunction (typeof<'f>, runner) :?> 'f
F# does support the dynamic call operator. But you must implement yours. Here is a sample Implementation taken from http://www.fssnip.net/2U/title/Dynamic-operator-using-Dynamic-Language-Runtime
// Reference C# implementation of dynamic operations
#r "Microsoft.CSharp.dll"
open System
open System.Runtime.CompilerServices
open Microsoft.CSharp.RuntimeBinder
// Simple implementation of ? operator that works for instance
// method calls that take a single argument and return some result
let (?) (inst:obj) name (arg:'T) : 'R =
// TODO: For efficient implementation, consider caching of call sites
// Create dynamic call site for converting result to type 'R
let convertSite =
CallSite<Func<CallSite, Object, 'R>>.Create
(Binder.Convert(CSharpBinderFlags.None, typeof<'R>, null))
// Create call site for performing call to method with the given
// name and a single parameter of type 'T
let callSite =
CallSite<Func<CallSite, Object, 'T, Object>>.Create
(Binder.InvokeMember
( CSharpBinderFlags.None, name, null, null,
[| CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null);
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) |]))
// Run the method call using second call site and then
// convert the result to the specified type using first call site
convertSite.Target.Invoke
(convertSite, callSite.Target.Invoke(callSite, inst, arg))
You'd be able to use it as follows
// Dynamically invoke 'Next' method of 'Random' type
let o = box (new Random())
let a : int = o?Next(10)
As for the params you'd have to pass them as a Tuple something like
target?method(param1, param2) that would mean that the target method processes its argument as a Tuple and as such, some pattern matching may or may not be involved

Runtime error handling in Swift

I am fully aware that Swift doesn't have a try/catch mechanism to catch exceptions (OK, Swift 2.0 now supports them). I also understand that many API methods return a NSError that will be filled with an error object if something goes wrong. So please don't point me to this question: Error-Handling in Swift-Language
But this still doesn't explain how to react to runtime errors in your own code, like array-out-of-bounds accesses or force-unwrapping an optional value that is nil. For example:
var test: String?
test = nil
println(test!) //oops!
or
var arr = [0,1,2]
for i = 0...3 {
println(arr[i]) //oops!
}
Every programmer makes such mistakes occasionally and there should be a way to at least log them for later analysis. While debugging, Xcode can show us those, but what if this happens to an end-user or beta-tester? In pure C there is signal handling and it could be used in Objective-C as well. Is there something like this in Swift? A centralized callback entered just before the app dies?
Update:
Let me rephrase the question: in a large project, it is not feasible to manually check for the above errors on every loop and force-unwrapping. When a runtime error does happen eventually, is there a callback like Objective C's segfault handling or NSSetUncaughtExceptionHandler that will get called so that the error can be logged/e-mailed together with a stacktrace of the crash?
Edit: This answer is not updated with swift 2.0. As swift now has error handling I have not updated the below answer. Some aspect of error handling will be updated in future with swift 3.0. You can follow this answer Error-Handling in Swift-Language
Swift is made to be typeSafe language.It get error at compile time rather than waiting to cause at runtime.
In first example you are using Optional.
var test: String?
First understand meaning of optional.When you specifying optional you are saying it could be nil or have no value.Now when you unwrapping test you are saying i know this value is not nil.Please unwrap it i am sure about that.So its your responsibility to see where it nil.If you are not sure about that than you should use optional binding here.When you are unsure about value always use if condition while unwrrapping
if let notNilTest = test {
//use notNilTest
}
else{
//handle error
}
In second example it should make sense to have the runtime exception handling but you can easily get this with if condition having count.So in second example as developer you should use if condition to get count of array.
From swift guide:
If you try to use subscript syntax to retrieve or set a value for an
index that is outside of an array’s existing bounds, you will trigger
a runtime error. However, you can check that an index is valid before
using it, by comparing it to the array’s count property. Except when
count is 0 (meaning the array is empty), the largest valid index in an
array will always be count - 1, because arrays are indexed from zero.
They clearly mention about this and you should take care of these things to make your code less buggy.Some things they have provided and we should know about how to use these things.
Consider using a guard statement instead of multiple if lets.
var arr = [0,1,2]
for i = 0...3 {
Guard arr[i] != nil else {
Continue
}
println(arr[i]) //oops!
}
Or instead of
if let x = some value {
If let y = someOtherVal {
If let z = yetanotherVal {
Product = x * y* z
}
}
}
Is not nearly as neat as:
Let x = someVal
Let y = someOtherVal
Let z = yetAnotherVal
Guard x != nil,
y != nil,
z != nil
Else {
Return
}
Product = x * y * z

How to use tuples effectively in function?

Swift programming book says,
By returning a tuple with two distinct values, each of a different
type, the function provides more useful information about its outcome
than if it could only return a single value of a single type.
Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/gb/jEUH0.l
I searched on internet but couldn't find any examples of it.So I tried myself like example below, but if you've got better please let me know.. Thanks in advance.
var statusCode = 404
var statusMessage = "No Site"
let http404 = ( sCode : statusCode , sMessage : statusMessage)
func responseFromWS (foo : Int, bar : String) -> (param1 : Int, param2 : String)
{
statusCode = foo
statusMessage = bar
let httpProtocol = ( statusCode , statusMessage)
return httpProtocol
}
responseFromWS(500, "Internal Server Error")
In other languages (including objective c) you can return one value only (of any type), but in some cases you might need to return more than one value.
The pattern usually applied in those cases is to pass references to variables to the function for all additional return values - a typical case is a reference to a NSError * variable, which the function either sets to nil if no error occurs, or to an instance of NSError in case of error.
Such problem is elegantly solved in swift using multiple return values packed in a tuple.
The way you are using this features seems correct, but what's wrong is defining the statusCode and statusMessage variables outside the function scope:
func responseFromWS (foo : Int, bar : String) -> (code: Int, message: String)
{
let statusCode: Int = foo
let statusMessage: String = bar
return (code: statusCode, message: statusMessage)
// Note: you can also write as follows, because the parameter names are defined in the function signature
// return (statusCode, statusMessage)
}
You can use the return value in different ways. As a tuple:
let response = responseFromWS(500, "Internal Server Error")
// Using named parameters
println(response.code) // Prints 500
println(response.message) // Prints "Internal Server Error"
// using parameters by index
println(response.0) // Prints 500
println(response.1) // Prints "Internal Server Error"
As individual variables:
let (code, message) = responseFromWS(500, "Internal Server Error")
println(code)
println(message)
As a subset of individual variables (if you need only a subset of the returned values):
// Assign message only, discard code
let (_, message) = responseFromWS(500, "Internal Server Error")
println(message)
In addition to the uses mentioned by #Antonio, I have used them to return "pseudo-structs" where a function calculates several values, but the definition of a new struct type would really not be used anywhere else.
An example: when calculating true bearing and distance on the surface of the earth, one may choose to return some kind of polar coordinate struct, but the reverse azimuth (not a trivial relation in true geodesy) is also calculated as a by product. In implementations in other languages I have done this by defining a struct type to return the three doubles - but this struct type is never used except to call this function! Better to say
let (distance, azimuth, reverseAzimuth) = coordinate(vectorTo: otherCoordinate)
than having your future self look up the definition of and then unpack some obscure struct.

Reading HTML contents of a URL in OCaml

I would like to write an OCaml function which takes a URL and returns a string made up of the contents of the HTML file at that location. Any ideas?
Thanks a lot!
Best,
Surikator.
I've done both of those things using ocurl and nethtml
ocurl to read the contents of the URL (tons of properties here; this is the minimum),
let string_of_uri uri =
try let connection = Curl.init () and write_buff = Buffer.create 1763 in
Curl.set_writefunction connection
(fun x -> Buffer.add_string write_buff x; String.length x);
Curl.set_url connection uri;
Curl.perform connection;
Curl.global_cleanup ();
Buffer.contents write_buff;
with _ -> raise (IO_ERROR uri)
and from nethtml; (you might need to set up a DTD for Nethtml.parse)
let parse_html_string uri =
let ch = new Netchannels.input_string (string_of_uri uri) in
let docs = Nethtml.parse ?return_pis:(Some false) ch in
ch # close_in ();
docs
Cheers!