As per the discussion "Scripting: How to route requests to different services", we have implemented the similar approach for JSON with Basic Auth and header values in Scripted Rule. We are getting Authentication Denied or Unsupported Media Conten

Steps Followed:

1. We have routed the requests to two different URL's using excel file/text file.

2. The ID is provided in URI path, validation is based on the same ID. If the ID exists in excel/text file then the request is forwarded to URL1 and if does not exist in excel/text file then it should be sent to URL2.

Issue observed in above steps:

Basic Auth header is not passed along with the requests. 

Script In Use:

using HP.SV.CSharp;
using System.Collections.Generic;
using System;

using System.Text;
using System.Net.Http;
using NPOI.SS.UserModel;
using System.IO;
using NPOI.XSSF.UserModel;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Net;
using HP.SV.DotNetRuleApi;
namespace HP.SV
{
public class CSharpRule
{
private static string ID1;
private static string ExcelFilePath = @"C:/VirtualRouter.xlsx";
private static string ExcelSheetName = "Sheet1";

private static string TextFilePath = @"C:/VirtualRouter.txt";
private static string result ;
private static string delimiter = "|";
private static string searchInput = result;
private static string HttpheaderRESTAction = "RESTAction";
private static string HttpHeaderContentType = "Content-Type";
private static string HttpHeaderContentEncoding = "Content-Encoding";
/// <summary>
/// Main method.
/// </summary>;
public static void Execute(HpsvRootObject sv)
{
ID1 = sv.Request.HTTPInputParameters.UriPath;
//sv.MessageLogger.Warn(ID1);
Dictionary<string, string> httpHeaders = GetHttpHeaders(sv.Request);
byte[] payload = Convert.FromBase64String(sv.Request.BinaryContent.Data);
string targeturl = GetTargetUrl(httpHeaders, payload);
// log target URL for debugging purposes
sv.MessageLogger.Warn(targeturl);
HttpResponseMessage httpResponse = DoHttpPost(targeturl, httpHeaders, payload);
CopyToHpsvResponse(httpResponse, sv.Response);
string Uripath = sv.GetOrCreate(x => x.Request.HTTPInputParameters).UriPath.ToString();
}

/// <summary>
/// Copies data from the .NET HttpResponse structure to SV structure.
/// </summary>

public static void CopyToHpsvResponse(HttpResponseMessage httpResponse, HpsvResponse hpsvResponse)
{
hpsvResponse.HTTPOutputParameters.StatusCode = (long)httpResponse.StatusCode;
hpsvResponse.BinaryContent.Data = Convert.ToBase64String(httpResponse.Content.ReadAsByteArrayAsync().Result);
hpsvResponse.HTTPOutputParameters.Headers.Content_Type = httpResponse.Content.Headers.ContentType.ToString();
}

/// <summary>
/// Returns URL where we want to forward the request.
/// </summary>
public static string GetTargetUrl(Dictionary<string, string> headers, byte[] payload)
{
// load Excel data
Dictionary<string, string> idToUrlMap = ReadExcelData(ExcelFilePath, ExcelSheetName);



result = ID1;// this value is taken uri path
string target_endpoint_url;
idToUrlMap.TryGetValue(result, out target_endpoint_url);
if (target_endpoint_url == null)
{
bool found = false;
try
{
string[] lines = File.ReadAllLines(TextFilePath);
foreach (string line in lines)
{
string[] parts = line.Split(new string[] { delimiter },StringSplitOptions.RemoveEmptyEntries);
if (parts.Length == 2)
{
string substringBeforeDelimiter = parts[0].Trim();
string substringAfterDelimiter = parts[1].Trim();
if (substringBeforeDelimiter == result)
{
target_endpoint_url = substringAfterDelimiter;
found = true;
break;
}
}
}
if (!found)
{
target_endpoint_url = "">httP://URL/customers/"+ID1;

}
}
catch (Exception e)
{
// sv.MessageLogger.Warn("Error occurred while reading from text file: " + e.Message);
target_endpoint_url = "";">httP://URL/customers/"+ID1;";
}
}
return target_endpoint_url;
}

/// <summary>
/// Extracts HTTP headers from SV request structure.
/// </summary>

private static Dictionary<string, string> GetHttpHeaders(HpsvRequest httpRequest)

{
Dictionary<string, string> headers = new Dictionary<string, string>();
foreach (KeyValuePair<string, object> header in httpRequest.HTTPInputParameters.Headers.GetAllProperties())
{
headers.Add(header.Key, (string)header.Value);
}
return headers;
}

/// <summary>
/// Invokes the remote service and returns the response.
/// </summary>

private static HttpResponseMessage DoHttpPost(string requestUri, Dictionary<string, string> httpHeaders, byte[] payload)
{
HttpContent httpContent = CreateHttpContent(httpHeaders, payload);
HttpClientHandler handler = new HttpClientHandler();

 string token = "your_basic_token"; // Replace with your actual token

  string basicAuthHeader = "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes(token));


handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.ServerCertificateCustomValidationCallback =
(httpRequestMessage, cert, cetChain, policyErrors) =>
{
return true;
};
HttpClient client = new HttpClient(handler,true);
client.DefaultRequestHeaders.Add("Authorization",basicAuthHeader);
HttpResponseMessage response = client.PostAsync(requestUri, httpContent).Result;
return response;
}

/// <summary>
/// Creates the .NET request object.
/// </summary>

private static HttpContent CreateHttpContent(Dictionary<string, string> headers, byte[] payload) {

HttpContent httpContent = new ByteArrayContent(payload);
foreach (KeyValuePair<string, string> header in headers)
{
if (header.Key == HttpHeaderContentType)
{
httpContent.Headers.ContentType.MediaType = header.Value;
}
else if (header.Key == HttpHeaderContentEncoding)
{
httpContent.Headers.ContentEncoding.Add(header.Value);
}
else
{
httpContent.Headers.Add(header.Key, header.Value);
}
}
return httpContent;
}

/// <summary>
/// Reads data from Excel.
/// </summary>

private static Dictionary<string, string> ReadExcelData(string excelFilePath, string SheetName) {

// read
IWorkbook workbook = ReadWorkbook(excelFilePath);

// get value
ISheet sheet = workbook.GetSheet(SheetName);

Dictionary<string, string> idToUrlMap = new Dictionary<string, string>();
bool next = true;
for (int i = 0; next; i++)
{
IRow row = sheet.GetRow(i);
if (row != null)
{
string ID1 = row.GetCell(0)?.ToString();
string target_endpoint_url = row.GetCell(1)?.ToString();
if( !idToUrlMap.ContainsKey(ID1))
{
idToUrlMap.Add(ID1, target_endpoint_url);
}
next = !string.IsNullOrEmpty(ID1);
}
else
{
next = false;
}
}
return idToUrlMap;
}

private static IWorkbook ReadWorkbook(string file)
{
IWorkbook workBook;
using (var fs = File.OpenRead(file))
{
workBook = new XSSFWorkbook(fs);
}
return workBook;
}
}
}

  • You might need to set the authorization header via specific Authorization property

    requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Basic", base64EncodedAuthenticationString);

    See following for more: stackoverflow.com/.../how-do-you-use-basic-authentication-with-system-net-http-httpclient

  • Hi Jakub,

    We have implemented above script line and we are still facing the Unsupported Media type. Attached code for the same.

     The (BAN1) ID is provided in URI path, validation is based on the same (BAN1)ID. If the (BAN1)ID exists in excel/text file then the request is forwarded to URL1 and if does not exist in excel/text file then it should be sent to URL2.

    // In this scripted rule, you can use C# to interact with request, response and other data structures.
    //
    // For Scripted rule documentation, see:
    // - Generic Help:  https://admhelp.microfocus.com/sv/en/2022-2022-r2/Help/Content/UG/t_scripted_rule.htm
    // - API documentation: https://admhelp.microfocus.com/documents/sv/DotNetRuleApi/2022-2022-r2
    
    using HP.SV.CSharp;
    using System.Collections.Generic;
    using System;
    using System.Text;
    using System.Net.Http;
    using System.Net.Http.Headers;
    using NPOI.SS.UserModel;
    using System.IO;
    using NPOI.XSSF.UserModel;
    using System.Linq;
    using System.Threading.Tasks;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Linq;
    using System.Net;
    using HP.SV.DotNetRuleApi;
    
    namespace HP.SV 
    {
        public class CSharpRule 
        {
           private static string BAN1;
           private static string ExcelFilePath = @"Excel file path";
           private static string ExcelSheetName = "Sheet1";
           private static string DefaultUrl = ("Url"+BAN1+"Parameters").ToString() ;
           private static string TextFilePath = @"Text file path";
           private static string username = "";
           private static string password = "";
           private static string Credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{username}:{password}"));
             
           private static string result ;
           private static string delimiter = "|";
           private static string searchInput = result;
           private static string HttpheaderRESTAction = "RESTAction";
           private static string HttpHeaderContentType  = "Content-Type";
           private static string HttpHeaderContentEncoding = "Content-Encoding";
    
           // Main method.
           public static void  Execute(HpsvRootObject sv)
           {
            BAN1 = sv.Request.HTTPInputParameters.UriPath;
            	
            Dictionary<string, string> httpHeaders = GetHttpHeaders(sv.Request);
            byte[] payload = Convert.FromBase64String(sv.Request.BinaryContent.Data);
            string targeturl = GetTargetUrl(httpHeaders,payload);
    
            sv.MessageLogger.Warn(targeturl);
            HttpResponseMessage httpResponse = DoHttpPost(targeturl, httpHeaders, payload);
            CopyToHpsvResponse(httpResponse, sv.Response);
           }
    
          // Copies data from the .NET HttpResponse structure to SV structure.
           private static void CopyToHpsvResponse(HttpResponseMessage httpResponse, HpsvResponse hpsvResponse) 
           {
                hpsvResponse.HTTPOutputParameters.StatusCode = (long)httpResponse.StatusCode;
                hpsvResponse.BinaryContent.Data = Convert.ToBase64String(httpResponse.Content.ReadAsByteArrayAsync().Result);
                hpsvResponse.HTTPOutputParameters.Headers.Content_Type = httpResponse.Content.Headers.ContentType.ToString();
           }            
            
           // Returns URL where we want to forward the request.
            private static string GetTargetUrl(Dictionary<string, string> headers, byte[] payload)
            {
             // load Excel data
             Dictionary<string, string> ssnToUrlMap = ReadExcelData(ExcelFilePath,ExcelSheetName);
             {
              result = BAN1;
    		 }
               string target_endpoint_url;
               ssnToUrlMap.TryGetValue(result, out target_endpoint_url);
               if (target_endpoint_url == null) 
                {
                    bool found = false;
                 try
                {
                string[] lines = File.ReadAllLines(TextFilePath);
                foreach (string line in lines)
                {
                string[] parts = line.Split(new string[] { delimiter },StringSplitOptions.RemoveEmptyEntries);
                if (parts.Length == 2)
                {
                     string substringBeforeDelimiter = parts[0].Trim();
                     string substringAfterDelimiter = parts[1].Trim();
                     if (substringBeforeDelimiter == result)
                     {
                      target_endpoint_url = substringAfterDelimiter;
                      found = true;
                      break;
                     }
                } 
                }
               if (!found)
                {
               target_endpoint_url= "Url"+BAN1+"Parameters";
                 }
                }
               catch (Exception e)
               {
                target_endpoint_url = "Url"+BAN1+"Parameters";
               }
                }
               return target_endpoint_url;
              }
    
           // Extracts HTTP headers from SV request structure.
           private static Dictionary<string, string> GetHttpHeaders(HpsvRequest httpRequest)
         	{
               Dictionary<string, string> headers = new Dictionary<string, string>();
                foreach (KeyValuePair<string, object> header in httpRequest.HTTPInputParameters.Headers.GetAllProperties())
                {
                headers.Add(header.Key, (string)header.Value);
               }
               return headers;
            }
    
           // Invokes the remote service and returns the response.
           private static HttpResponseMessage  DoHttpPost(string requestUri, Dictionary<string, string> httpHeaders, byte[] payload)
           {
                HttpContent httpContent = CreateHttpContent(httpHeaders,payload);
                HttpClientHandler handler = new HttpClientHandler();
               
              
                 
                handler.ClientCertificateOptions = ClientCertificateOption.Manual;
                handler.ServerCertificateCustomValidationCallback = 
                (httpRequestMessage, cert, cetChain, policyErrors) =>
                      {
                        return true;
                      };
                
                 HttpClient client = new HttpClient(handler,true);
                 client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",Credentials);
              
              HttpResponseMessage response = client.PostAsync(requestUri,httpContent).Result;
             return response;
            }
           
           // Creates the .NET request object.
           private  static HttpContent CreateHttpContent(Dictionary<string, string> headers, byte[] payload)
             {
                HttpContent httpContent   = new ByteArrayContent(payload);
                foreach (KeyValuePair<string, string> header in headers) 
                {
                  if (header.Key == HttpHeaderContentType) 
                    {
                      httpContent.Headers.ContentType.MediaType = header.Value;
                     }
                  else if (header.Key == HttpHeaderContentEncoding) 
                    {
                      httpContent.Headers.ContentEncoding.Add(header.Value);
                    } 
                  else
                     {
                      httpContent.Headers.Add(header.Key, header.Value);
                     }
                   }
                return httpContent;
              }
    
            // Reads data from Excel.
            private static Dictionary<string, string> ReadExcelData(string excelFilePath, string SheetName) {
    
                // read  
                IWorkbook workbook = ReadWorkbook(excelFilePath);
    
               // get value  
               ISheet sheet = workbook.GetSheet(SheetName);
    
               Dictionary<string, string> ssnToUrlMap = new Dictionary<string, string>();
               bool next = true;
              for (int i = 0; next; i++) 
               {
               IRow row = sheet.GetRow(i);
                if (row != null) 
                 {
                   string BAN1 = row.GetCell(0)?.ToString();
                   string target_endpoint_url = row.GetCell(1)?.ToString();
                if( !ssnToUrlMap.ContainsKey(BAN1))
                  {
                   ssnToUrlMap.Add(BAN1, target_endpoint_url);
                  }
                  next = !string.IsNullOrEmpty(BAN1);
                  } 
                else
                   {
                  next = false;
                    }
              }
             return ssnToUrlMap;
           }
            private static IWorkbook ReadWorkbook(string file) 
            {
              IWorkbook workBook;
              using (var fs = File.OpenRead(file)) 
              {
               workBook = new XSSFWorkbook(fs);
              }
              return workBook;
            }
          }
    }