<commit_before>﻿// ----------------------------------------------------------------------------
// (c) <NAME>, 2013
//
// This source code is subject to terms and conditions of the Apache License, Version 2.0. A 
// copy of the license can be found in the License.txt file at the root of this distribution. 
// By using this source code in any fashion, you are agreeing to be bound 
// by the terms of the Apache License, Version 2.0.
//
// You must not remove this notice, or any other, from this software.
// ----------------------------------------------------------------------------
namespace FlexSearch.Core

module HttpHelpers = 
    open FlexSearch
    open FlexSearch.Api
    open FlexSearch.Api.Message
    open FlexSearch.Core
    open FlexSearch.Utility
    open Microsoft.Owin
    open Newtonsoft.Json
    open Newtonsoft.Json.Converters
    open ProtoBuf
    open System
    open System.Collections.Concurrent
    open System.IO
    open System.Linq
    open System.Net
    open System.Text
    open System.Threading
    
    let jsonSettings = new JsonSerializerSettings()
    
    jsonSettings.Converters.Add(new StringEnumConverter())
    
    /// Helper method to serialize cluster messages
    let protoSerialize (message : 'a) = 
        use stream = new MemoryStream()
        Serializer.Serialize(stream, message)
        stream.ToArray()
    
    /// Helper method to deserialize cluster messages
    let protoDeserialize<'T> (message : byte []) = 
        use stream = new MemoryStream(message)
        Serializer.Deserialize<'T>(stream)
    
    /// Write http response
    let writeResponse (statusCode : System.Net.HttpStatusCode) (response : obj) (owin : IOwinContext) = 
        let matchType format res = 
            match format with
            | "text/json" | "application/json" | "json" -> 
                owin.Response.ContentType <- "text/json"
                match owin.Request.Query.Get("callback") with
                | null -> 
                    let result = JsonConvert.SerializeObject(res, jsonSettings)
                    Some(Encoding.UTF8.GetBytes(result))
                | fname -> 
                    let result = sprintf "%s(%s);" fname (JsonConvert.SerializeObject(res, jsonSettings))
                    Some(Encoding.UTF8.GetBytes(result))
            | "application/x-protobuf" | "application/octet-stream" | "proto" -> 
                owin.Response.ContentType <- "application/x-protobuf"
                Some(protoSerialize (res))
            | _ -> None
        owin.Response.StatusCode <- int statusCode
        if response <> Unchecked.defaultof<_> then 
            let result = 
                if owin.Request.Uri.Segments.Last().Contains(".") then 
                    matchType 
                        (owin.Request.Uri.Segments.Last().Substring(owin.Request.Uri.Segments.Last().IndexOf(".") + 1)) 
                        response
                else if owin.Request.Accept = null then matchType "application/json" response
                else if owin.Request.Accept.Contains(",") then 
                    let header = owin.Request.Accept.Substring(0, owin.Request.Accept.IndexOf(","))
                    matchType header response
                else matchType owin.Request.Accept response
            match result with
            | None -> owin.Response.StatusCode <- int HttpStatusCode.NotAcceptable
            | Some(x) -> await (owin.Response.WriteAsync(x))
    
    /// Write http response
    let getRequestBody<'T when 'T : null> (request : IOwinRequest) = 
        let contentType = 
            if String.IsNullOrWhiteSpace(request.ContentType) then 
                if request.Uri.Segments.Last().Contains(".") then 
                    request.Uri.Segments.Last().Substring(request.Uri.Segments.Last().IndexOf(".") + 1)
                else 
                    // Default to json
                    "application/json"
            else request.ContentType
        if request.Body.CanRead then 
            match contentType with
            | "text/json" | "application/json" | "application/json; charset=utf-8" | "application/json;charset=utf-8" | "json" -> 
                let body = 
                    use reader = new System.IO.StreamReader(request.Body)
                    reader.ReadToEnd()
                if String.IsNullOrWhiteSpace(body) <> true then 
                    try 
                        match JsonConvert.DeserializeObject<'T>(body) with
                        | null -> 
                            Choice2Of2
                                (OperationMessage.WithDeveloperMessage
                                     (MessageConstants.HTTP_UNABLE_TO_PARSE, "No body is defined."))
                        | result -> Choice1Of2(result)
                    with ex -> 
                        Choice2Of2
                            (OperationMessage.WithDeveloperMessage(MessageConstants.HTTP_UNABLE_TO_PARSE, ex.Message))
                else Choice2Of2(MessageConstants.HTTP_NO_BODY_DEFINED)
            | "application/x-protobuf" | "application/octet-stream" | "proto" -> 
                try <commit_msg>Refactored request response format code.<commit_after>﻿// ----------------------------------------------------------------------------
// (c) <NAME>, 2013
//
// This source code is subject to terms and conditions of the Apache License, Version 2.0. A 
// copy of the license can be found in the License.txt file at the root of this distribution. 
// By using this source code in any fashion, you are agreeing to be bound 
// by the terms of the Apache License, Version 2.0.
//
// You must not remove this notice, or any other, from this software.
// ----------------------------------------------------------------------------
namespace FlexSearch.Core

module HttpHelpers = 
    open FlexSearch
    open FlexSearch.Api
    open FlexSearch.Api.Message
    open FlexSearch.Core
    open FlexSearch.Utility
    open Microsoft.Owin
    open Newtonsoft.Json
    open Newtonsoft.Json.Converters
    open ProtoBuf
    open System
    open System.Collections.Concurrent
    open System.IO
    open System.Linq
    open System.Net
    open System.Text
    open System.Threading
    
    let jsonSettings = new JsonSerializerSettings()
    
    jsonSettings.Converters.Add(new StringEnumConverter())
    
    /// Helper method to serialize cluster messages
    let protoSerialize (message : 'a) = 
        use stream = new MemoryStream()
        Serializer.Serialize(stream, message)
        stream.ToArray()
    
    /// Helper method to deserialize cluster messages
    let protoDeserialize<'T> (message : byte []) = 
        use stream = new MemoryStream(message)
        Serializer.Deserialize<'T>(stream)
    
    /// Get request format from the request object
    /// Defaults to json
    let private getRequestFormat (request : IOwinRequest)  =
        if String.IsNullOrWhiteSpace(request.ContentType) then 
            if request.Uri.Segments.Last().Contains(".") then 
                request.Uri.Segments.Last().Substring(request.Uri.Segments.Last().IndexOf(".") + 1)
            else 
                // Default to json
                "application/json"
        else request.ContentType

    /// Get response format from the owin context
    /// Defaults to json
    let private getResponseFormat (owin : IOwinContext) = 
        if owin.Request.Uri.Segments.Last().Contains(".") then 
                owin.Request.Uri.Segments.Last().Substring(owin.Request.Uri.Segments.Last().LastIndexOf(".") + 1) 
        else if owin.Request.Accept = null then 
            "application/json"
        else if owin.Request.Accept = "*/*" then
            "application/json"
        else if owin.Request.Accept.Contains(",") then 
            owin.Request.Accept.Substring(0, owin.Request.Accept.IndexOf(","))
        else owin.Request.Accept

    /// Write http response
    let writeResponse (statusCode : System.Net.HttpStatusCode) (response : obj) (owin : IOwinContext) = 
        let matchType format res = 
            match format with
            | "text/json" | "application/json" | "json" -> 
                owin.Response.ContentType <- "text/json"
                match owin.Request.Query.Get("callback") with
                | null -> 
                    let result = JsonConvert.SerializeObject(res, jsonSettings)
                    Some(Encoding.UTF8.GetBytes(result))
                | fname -> 
                    let result = sprintf "%s(%s);" fname (JsonConvert.SerializeObject(res, jsonSettings))
                    Some(Encoding.UTF8.GetBytes(result))
            | "application/x-protobuf" | "application/octet-stream" | "proto" -> 
                owin.Response.ContentType <- "application/x-protobuf"
                Some(protoSerialize (res))
            | _ -> None
        owin.Response.StatusCode <- int statusCode
        if response <> Unchecked.defaultof<_> then 
            let format = getResponseFormat owin
            let result = matchType format response   
            match result with
            | None -> owin.Response.StatusCode <- int HttpStatusCode.InternalServerError
            | Some(x) -> await (owin.Response.WriteAsync(x))
    
    /// Write http response
    let getRequestBody<'T when 'T : null> (request : IOwinRequest) = 
        let contentType = getRequestFormat request
        if request.Body.CanRead then 
            match contentType with
            | "text/json" | "application/json" | "application/json; charset=utf-8" | "application/json;charset=utf-8" | "json" -> 
                let body = 
                    use reader = new System.IO.StreamReader(request.Body)
                    reader.ReadToEnd()
                if String.IsNullOrWhiteSpace(body) <> true then 
                    try 
                        match JsonConvert.DeserializeObject<'T>(body) with
                        | null -> 
                            Choice2Of2
                                (OperationMessage.WithDeveloperMessage
                                     (MessageConstants.HTTP_UNABLE_TO_PARSE, "No body is defined."))
                        | result -> Choice1Of2(result)
                    with ex -> 
                        Choice2Of2
                            (OperationMessage.WithDeveloperMessage(MessageConstants.HTTP_UNABLE_TO_PARSE, ex.Message))
                else Choice2Of2(MessageConstants.HTTP_NO_BODY_DEFINED)
            | "application/x-protobuf" | "application/octet-stream" | "proto" -> 
                try 
{'fraction_non_alphanumeric': 0.11970359110773324, 'fraction_numerical': 0.004370131103933118, 'mean_word_length': 1.7061696658097687, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2957717', 'n_tokens_mistral': 2725, 'n_tokens_neox': 2585, 'n_words': 675}