3 people like it.
Like the snippet!
Simple synchronous HTTP Server
Needed to receive an OAuth 2 response so used simple http listener
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
|
(*
[CONTEXT] Trying to access box.com for file storage
(in interactive console app)
Concept could be used for other OAuth providers
Box.com has the following info:
To complete an OAuth 2.0 flow the following steps need to be completed.
1. Configure the Box SDK
2. Redirect the user to the Box website (with REDIRECT_URI)
3. The user grants the application access
4. Exchange the authorization code for an access token
Step 4: "The user is redirected to your application's redirect URL
with a query parameter containing a short-lived authorization code."
Needed to receive that request to exchange the code
So have the console app create a 'webserver' and capture code [this script].
*)
open System
open System.Net
let host = "http://localhost:8888/"
let hl = new HttpListener()
hl.Prefixes.Add host
hl.Start()
printfn "Listening for HTTP on %s ..." host
// Note: The GetContext method blocks while waiting for a request.
let context = hl.GetContext()
///incoming request
let request = context.Request
///querystring code key for OAuth2
let code = request.QueryString.["code"]
//printfn "Url.OriginalString: %O" request.Url.OriginalString
//printfn "RawUrl: %O" request.RawUrl
//printfn "%s" code
// Obtain a response object to make outgoing response.
//Already have what is needed (querystring code)
//the response lets the sending server know I got it
let response = context.Response
let responseString =
"""
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>OAuth2 Code Page</title>
</head>
<body>
<!-- page content -->
Got the code! @ """ + DateTime.Now.ToString() + """
</body>
</html>
"""
let encoding = System.Text.Encoding.UTF8
let txt = encoding.GetBytes responseString
//each are optional header options. Actually works ok without them
response.ContentEncoding <- encoding
response.ContentLength64 <- Convert.ToInt64( txt.Length )
response.ContentType <- System.Net.Mime.MediaTypeNames.Text.Html
response.KeepAlive <- false
//send response
response.OutputStream.Write (txt, 0, txt.Length)
//must close
response.OutputStream.Close()
//stop the HTTP listener
hl.Stop();
//the value I was wanting
//as part of a client side OAuth 2 ping pong
printfn "%s" code
//next use this to send new http request for exchange for Access Token
|
namespace System
namespace System.Net
val host : string
val hl : HttpListener
Multiple items
type HttpListener =
new : unit -> HttpListener
member Abort : unit -> unit
member AuthenticationSchemeSelectorDelegate : AuthenticationSchemeSelector with get, set
member AuthenticationSchemes : AuthenticationSchemes with get, set
member BeginGetContext : callback:AsyncCallback * state:obj -> IAsyncResult
member Close : unit -> unit
member DefaultServiceNames : ServiceNameCollection
member EndGetContext : asyncResult:IAsyncResult -> HttpListenerContext
member ExtendedProtectionPolicy : ExtendedProtectionPolicy with get, set
member ExtendedProtectionSelectorDelegate : ExtendedProtectionSelector with get, set
...
nested type ExtendedProtectionSelector
--------------------
HttpListener() : HttpListener
val printfn : format:Printf.TextWriterFormat<'T> -> 'T
val context : HttpListenerContext
val request : HttpListenerRequest
incoming request
val code : string
querystring code key for OAuth2
val response : HttpListenerResponse
val responseString : string
Multiple items
type DateTime =
struct
new : ticks:int64 -> DateTime + 10 overloads
member Add : value:TimeSpan -> DateTime
member AddDays : value:float -> DateTime
member AddHours : value:float -> DateTime
member AddMilliseconds : value:float -> DateTime
member AddMinutes : value:float -> DateTime
member AddMonths : months:int -> DateTime
member AddSeconds : value:float -> DateTime
member AddTicks : value:int64 -> DateTime
member AddYears : value:int -> DateTime
...
end
--------------------
DateTime ()
(+0 other overloads)
DateTime(ticks: int64) : DateTime
(+0 other overloads)
DateTime(ticks: int64, kind: DateTimeKind) : DateTime
(+0 other overloads)
DateTime(year: int, month: int, day: int) : DateTime
(+0 other overloads)
DateTime(year: int, month: int, day: int, calendar: Globalization.Calendar) : DateTime
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int) : DateTime
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, kind: DateTimeKind) : DateTime
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, calendar: Globalization.Calendar) : DateTime
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int) : DateTime
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int, kind: DateTimeKind) : DateTime
(+0 other overloads)
property DateTime.Now: DateTime with get
val encoding : Text.Encoding
namespace System.Text
type Encoding =
member BodyName : string
member Clone : unit -> obj
member CodePage : int
member DecoderFallback : DecoderFallback with get, set
member EncoderFallback : EncoderFallback with get, set
member EncodingName : string
member Equals : value:obj -> bool
member GetByteCount : chars:char[] -> int + 5 overloads
member GetBytes : chars:char[] -> byte[] + 7 overloads
member GetCharCount : bytes:byte[] -> int + 3 overloads
...
property Text.Encoding.UTF8: Text.Encoding with get
val txt : byte []
type Convert =
static val DBNull : obj
static member ChangeType : value:obj * typeCode:TypeCode -> obj + 3 overloads
static member FromBase64CharArray : inArray:char[] * offset:int * length:int -> byte[]
static member FromBase64String : s:string -> byte[]
static member GetTypeCode : value:obj -> TypeCode
static member IsDBNull : value:obj -> bool
static member ToBase64CharArray : inArray:byte[] * offsetIn:int * length:int * outArray:char[] * offsetOut:int -> int + 1 overload
static member ToBase64String : inArray:byte[] -> string + 4 overloads
static member ToBoolean : value:obj -> bool + 17 overloads
static member ToByte : value:obj -> byte + 18 overloads
...
Convert.ToInt64(value: DateTime) : int64
(+0 other overloads)
Convert.ToInt64(value: string) : int64
(+0 other overloads)
Convert.ToInt64(value: decimal) : int64
(+0 other overloads)
Convert.ToInt64(value: float) : int64
(+0 other overloads)
Convert.ToInt64(value: float32) : int64
(+0 other overloads)
Convert.ToInt64(value: int64) : int64
(+0 other overloads)
Convert.ToInt64(value: uint64) : int64
(+0 other overloads)
Convert.ToInt64(value: uint32) : int64
(+0 other overloads)
Convert.ToInt64(value: int) : int64
(+0 other overloads)
Convert.ToInt64(value: uint16) : int64
(+0 other overloads)
namespace System.Net.Mime
type MediaTypeNames =
nested type Application
nested type Image
nested type Text
type Text =
static val Plain : string
static val Html : string
static val Xml : string
static val RichText : string
field Mime.MediaTypeNames.Text.Html: string = "text/html"
More information