I have a lambda function where I am making an api call which returns uuid on success and errorMessage on failure
try:
#make api call
return {
'statusCode': 200,
'body': json.dumps({'uuid':uniqueuuid})
}
except Exception as error:
return {
'statusCode': 500,
'body': json.dumps({'errorMessage':f"P56"})
}
For the success response from lambda, I can able to extract the body values in C#. In the below method,
I can able to get the uuid value returned from lambda. But when there is an exception from lambda, I want to
extract the errorMessage value which is "P56". On exception from lambda, it is picked up by catch block
and the exception has 'remote server returned an error 500' which is correct, but how do I extract the status code and errorMessage value in
the exception block. Or should I return statusCode as 200 for both success and failure from lambda
and extract either uuid or errorMessage in the try block of C#.
C# method:
private JObject GetDataFromLambda()
{
JObject jObj = null;
try
{
using (var client = new WebClient())
{
//define payload data
var result = client.UploadString($"https://xxx",
WebRequestMethods.Http.Post, data)
jObj = JObject.Parse(result);
var uuid= jObj["uuid"].Value<string>();
}
}
catch (Exception ex)
{
}
}
Can you try writing the below code in Lambda?
raise Exception('Something is wrong')
Based on the documentation, something like this should work:
private JObject GetDataFromLambda(string data)
{
JObject jObj = null;
try
{
using (var client = new WebClient())
{
//define payload data
var result = client.UploadString($"https://xxx",
WebRequestMethods.Http.Post, data)
jObj = JObject.Parse(result);
var uuid = jObj["uuid"].Value<string>();
}
}
catch (WebException ex)
{
if (ex.Status == WebExceptionStatus.ProtocolError)
{
var response = (HttpWebResponse)ex.Response;
var encoding = System.Text.Encoding.UTF8;
var sr = new StreamReader(response.GetResponseStream(), encoding);
string json = sr.ReadToEnd();
var errObj = JObject.Parse(json);
var httpStatusCode = response.StatusCode;
var errorMessage = errObj["errorMessage"].Value<string>();
}
}
return jObj;
}
Documentation:
WebException.Response: https://learn.microsoft.com/en-us/dotnet/api/system.net.webexception.response?view=net-6.0#system-net-webexception-response
HttpWebResponse.GetResponseStream(): https://learn.microsoft.com/en-us/dotnet/api/system.net.httpwebresponse.getresponsestream?view=net-6.0#system-net-httpwebresponse-getresponsestream
Related
I build a service to call API from Python flask. This is my Service
public string CheckStatus(string json)
{
Utils log = new Utils();
string ResponseString = "";
HttpWebResponse response = null;
try
{
string schedulingAPIUrl = ConfigurationManager.AppSettings["SchedulingAPI_URL"];
var request = (HttpWebRequest)WebRequest.Create(string.Format(schedulingAPIUrl + "{0}", "CheckStatus"));
request.Accept = "application/json";
request.Method = "POST";
request.Timeout = Timeout.Infinite;
request.KeepAlive = true;
var myContent = json;
var data = Encoding.ASCII.GetBytes(myContent);
request.ContentType = "application/json";
request.ContentLength = data.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
response = (HttpWebResponse)request.GetResponse();
ResponseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
}
catch (WebException ex)
{
if (ex.Status == WebExceptionStatus.ProtocolError)
{
response = (HttpWebResponse)ex.Response;
ResponseString = "Some error occurred: " + response.StatusCode.ToString();
}
else
{
ResponseString = "Some error occurred: " + ex.Status.ToString();
}
}
return ResponseString;
}
My Service will transfer a parameter is a list of many dictionaries to my API. If the Parameter has an amount of ~ 10000 dictionaries, everything is ok. But If it has to amount to 1 million dictionaries or more, after my API run 8-10minutes, I get an error: "500 InternalServerError".
I use wfastcgi, IIS to deploy my API.
I don't know the reason for the 500 error being from my Service or my API.
When I user types in search box and submits, this is how I set the url:
const submitHandler = (event: FormEvent) => {
event.preventDefault();
if (keyword) {
Router.push({ pathname: "", query: { keyword: keyword, page: 1 } });
} else {
Router.push(Router.router?.asPath as string);
}
};
this is how it looks on the url:"http://localhost:4500/?keyword=ca&page=1"
I use Next.js for front end and this is how I send the query params.
export const getServerSideProps = wrapper.getServerSideProps(
async (context) => {
const { store, query } = context;
console.log("params", query);
store.dispatch(fetchProductsStart(query));
store.dispatch(END);
await (store as SagaStore).sagaTask.toPromise();
const state = store.getState();
const productListState = state.productList ? state.productList : null;
return { props: { productListState } };
}
);
console.log("params", query) returns this object:"{ keyword: 'g', page: '1' }". This is what I am sending to backend.
Here is "fetchProductsStart"
export const fetchProductsStart = (
queryParams: {keyword:string,page:string}
): actions.IFetchProductsStart => ({
type: ProductListActionTypes.PRODUCT_LIST_START,
payload: queryParams,
});
This is how I tried to get the params in the backend:
#api_view(['GET'])
def getProducts(request):
q=request.query_params.get("page")
print("page query param",q)
query = request.query_params
print("query_params",query)
print("page query param",q) returns "None"
print("query_params",query) returns "<QueryDict: {'[object Object]': ['']}>"
The issue so far I was sending an object. Instead I stringified it "
store.dispatch(fetchProductsStart(JSON.stringify(query)));
now in backend
query = request.query_params
print("query",query)
it prints: query <QueryDict: {'{"keyword":"m","page":"1"}': ['']}>
but request.query_params.get("keyword") is still not working. It returns None
Try getting request parameters like this request.GET.get('param_name')
the problem was the way how I passed the query params to the backend:
Instead of this store.dispatch(fetchProductsStart(JSON.stringify(query)))
store.dispatch(
fetchProductsStart(`keyword=${query["keyword"]}&page=${query["page"]}`)
);
I'm looking to convert this Python request to a Swift script.
Here is my working python script that returns the accessToken!
#!/usr/bin/python
import requests
import json
#MAKE THE REQUEST
URL = "http://this/is/the/url"
headers = {
'Accept': "application/json",
"Accept-Language": "en_US"
}
data = {
"grant_type": "password",
"username" : "GROUP\SITE\USERNAME",
"password" : "somepassword"
}
r = requests.get(url = URL, params = headers, data = data)
data = r.json()
accessToken = data['access_token']
print(accessToken)
When I run the Swift Playground for the code below nothing is returned!
It seems the script exits at guard let data = data else { return }
How could I get the same results as the Python Script above.
I've tried implementing URLComponents using this tutorial...
import UIKit
var url = "http://just/the/url"
extension Dictionary {
func percentEncoded() -> Data? {
return map { key, value in
let escapedKey = "\(key)"
let escapedValue = "\(value)"
print(escapedKey + "=" + escapedValue)
return escapedKey + "=" + escapedValue
}
.joined(separator: "&")
.data(using: .utf8)
}
}
extension CharacterSet {
static let urlQueryValueAllowed: CharacterSet = {
let generalDelimitersToEncode = ":#[]#" // does not include "?" or "/" due to RFC 3986 - Section 3.4
let subDelimitersToEncode = "$&'()*+,;="
var allowed = CharacterSet.urlQueryAllowed
allowed.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
return allowed
}()
}
var request = URLRequest(url: URL(string:url)!)
request.httpMethod = "GET"
let parameters: [String: String] = [
"grant_type":"password",
"username":"GROUP\\SITE\\USER",
"password":"somePassword"
]
request.httpBody = parameters.percentEncoded()
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.setValue("application/XML", forHTTPHeaderField: "Accept")
let config = URLSessionConfiguration.default
URLSession(configuration: config).dataTask(with: request) { (data, response, err) in
guard let data = data else { return }
print(data)
guard let dataAsString = String(data: data, encoding: .utf8)else {return}
print(dataAsString)
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
print("Bad Credentials")
return
}
//HTTP Status Code!
print("HTTP RESPONSE:"+"\(httpResponse.statusCode)")
//
}.resume()
If I remember correctly, starting in iOS 13, you cant have httpBody for a GET call, so you'll either need to switch to a POST/PUT or add the params into the url string (See below)
You also had different Accept headers in your python vs. swift. One was xml the other was json.
var urlComponents = URLComponents(string: "http://this/is/the/url")
urlComponents?.queryItems = [
URLQueryItem(name: "grant_type", value: "password"),
URLQueryItem(name: "username", value: "username"),
URLQueryItem(name: "password", value: "somepassword")
]
guard let url = urlComponents?.url else { return } // You can print url here to see how it looks
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.setValue("en_US", forHTTPHeaderField: "Accept-Language")
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data,
let response = response as? HTTPURLResponse,
error == nil else {
print("error", error ?? "Unknown error")
return
}
print(response)
guard (200 ... 299) ~= response.statusCode else {
print("response = \(response)")
return
}
let responseString = String(data: data, encoding: .utf8)
print(responseString)
}
task.resume()
The problem was the following...
request.httpMethod = "GET"
I had to change the get to "POST" and now I have the token!!!!
I was confused because the python script used GET. I had a bash script that that used curl to get the token displayed the logged post.
In short my above Swift Playground now works by changing the request.httpMethod to "POST". THANKS FOR ALL THE HELP
When consuming a Hug REST endpoint from .net JSON has embedded characters. A complete failing example posted below. Any help greatly appreciated.
Python
#hug.post('/test')
def test(response, body=None):
input = body.get('input')
print('INSIDE TEST ' + input)
if input:
dict = {"lastname":"Jordan"}
dict["firstname"] = input
return json.dumps(dict, sort_keys=True, default=str)
.NET (can only use .net 3.5)
private static object GetParsedData(string data)
{
var posturl = "http://localhost:8000/test";
try
{
using (var client = new WebClient())
{
// upload values is the POST verb
var values = new NameValueCollection()
{
{ "input", data },
};
var response = client.UploadValues(posturl, values);
var responseString = Encoding.UTF8.GetString(response);
var settings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
MissingMemberHandling = MissingMemberHandling.Ignore
};
JObject rss = JObject.Parse(responseString);
Console.WriteLine((string)rss["lastname"]);
}
}
catch (WebException ex)
{
if (ex.Response is HttpWebResponse)
{
var code = ((HttpWebResponse)ex.Response).StatusCode;
var desc = ((HttpWebResponse)ex.Response).StatusDescription;
}
//_logger.Error(ex.Message);
}
return false;
}
responseString looks like this:
"\"{\\\"firstname\\\": \\\"Mike\\\", \\\"lastname\\\": \\\"Jordan\\\"}\""
JObject.Parse throws error:
Newtonsoft.Json.JsonReaderException:
'Error reading JObject from JsonReader. Current JsonReader item is not an object: String. Path '', line 1, position 53.
Workaround - If I do something horrible like this to responseString JObject parses correctly:
str = str.Replace("\\", "");
str = str.Substring(1, len - 2);
Whats going on?
The default hug output format is json; it is not necessary to call json.dumps on return values, hug will do this automatically.
So i'm working on converting a java program I have over to python. In my java code I have a http get call that looks like this.
sslContext.init(null, new TrustManager[] { new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
} }, new SecureRandom());
try {
CloseableHttpClient httpclient = HttpClients.custom()
.setSSLSocketFactory(new org.apache.http.conn.ssl.SSLSocketFactory(sslContext)).build();
String authString = username + ":" + password;
byte[] authEncBytes = Base64.encodeBase64(authString.getBytes());
String authStringEnc = new String(authEncBytes);
HttpGet httpGet = new HttpGet(envURL);
httpGet.setHeader("Content-Type", "application/json");
httpGet.setHeader("Authorization", "Basic " + authStringEnc);
CloseableHttpResponse httpGetResponse = httpclient.execute(httpGet);
HttpEntity entityResponse = httpGetResponse.getEntity();
String result = EntityUtils.toString(entityResponse);
EntityUtils.consume(entityResponse);
JSONParser parser = new JSONParser();
thresholdContent = (JSONArray) parser.parse(result);
} catch (Exception e) {
e.printStackTrace();
}
i'm trying to find the cleanist way to do this in python 3.x. Or I guess the standered for doing something like this in python.
I've tried soemthing like:
conn = requests.get(env, headers={"content-type":"application/json"}, auth=(userName,password))
but have not had much luck.
With requests in python you need to pass the url
conn = requests.get(url = 'https://myurl', headers = {'Content-Type':'application/json'})