Site 24×7 and JSONPath Example

We had an issue a couple of days ago where two points of failure caused some downtime and so I spent most of today revisiting all my monitors to give us as much warning as possible if one of our services fails.

One particular API I set up lives on the as400 (iSeries) and operates off of it’s ZendCore server in PHP.  I quickly scripted a page to verify:  connection between ZendCore PHP and db2, that the connection to that endpoint was in fact SSL, and on what port.

The PHP code is very simple and returns a JSON string that looks like this:

{
    "AS400CONNECTION": true,
    "SSL": true,
    "PORT": "633"
}

The slight problem today was figuring out how to get Site 24×7 to not just verify the link, but check the JSON values and verify it is what I need.  If not, then send the alert.  In this case, I want to verify AS400CONNECTION is true and SSL is true.

Site 24×7 suggests using a REST API monitor and then asserting the value in JSONPath.  I was completely new to this and finding a good clean example was a bit tough, hopefully this saves someone some time.  Here’s how I setup the JSONPath expression:

$[?(@.AS400CONNECTION==true)]
$[?(@.SSL==true)]

For a full screenshot of the setup I did to make this work click here.

 

 

 

Continue Reading

First Heroku App: Small API in PHP to Talk to .Net Core

I’ve recently been curious about switching to a time API for my time stamps and removing any dependency the app might have on the server for a timestamp.  Upon Googling I found some paid services, some free and of the free ones, I noticed one was hosted on Heroku.  I’ve heard of Heroku, but never had a reason to attempt to use it.  This was the perfect chance.

How I Created a Small “GetTime” API

First, I created a free account on Heroku, nothing special.  After verifying my email, I logged in to my Heroku Dashboard and up on the right hand corner, selected Create New App.  I named it my company-api and out popped an app.

I decided on just plain, legacy PHP and a simple DateTime string passed thru JSON encode, just to get started.  No authentication, no timezone,  just a simple spit out if a request to the site came, like this:

<?php
    header('Content-type:application/json;charset=utf-8');

    $DateTime = new DateTime();
    $currentTime = $DateTime->format("Y-m-d H:i:s");
    echo json_encode($currentTime);
?>

I created a Git repo for this brand new file and pushed it out.  Then, I went back to Heroku, Dashboard, My App and Deploy.  I selected Github as my deploy “resource” and selected the new repo I just made along with correpsonding branch.

I hit manual deploy and Heroku runs off to my GitHub repo, grabs the code, compiles and publishes.

It failed.

Beginner Troubles

My first problem was that Heroku could not determine what language I had chosen for my app (you’d think the <?php would give it away …).  You need either one of two things:  a composer.json file or an index.php file (for legacy, like mine).  I renamed my file to index.php and all I needed now was a “builder pack”.

To add a builder pack, I went back to Heroku, Dashboard, My App and Settings.  Under builder pack, I added one for: “php”.  Save settings and done.

I went back to Deploy, Manual Deploy and had a successful output.  Yay!  First Heroku app!

Adding Some Security

I want to make sure this API is receiving and sending JSON, so there’s a few IF’s I make the request go through before I hit logic on my PHP page.  I also want to (lightly) secure the requests made to this API and monitor our usage of it for metrics information (and future investment).  Since this itty bitty API is just relying on 1 index.php file, I figure this can be a sort of “router” for future API’s.  So, this is what I added to the final PHP file:

  • Verify the request is in JSON
  • Require two variables passed:
    • a secret api “key”
    • an api “request”
  • Use a switch statement to forward to needed method

 

The final, simple 1 page PHP Heroku API:

<?php
header('Content-type:application/json;charset=utf-8');

//Make sure that it is a POST request.
if(strcasecmp($_SERVER['REQUEST_METHOD'], 'POST') != 0){
    throw new Exception('Request method must be POST!');
}

//Make sure that the content type of the POST request has been set to application/json
$contentType = isset($_SERVER["CONTENT_TYPE"]) ? trim($_SERVER["CONTENT_TYPE"]) : '';
$contentIsJson = strpos($contentType, "application/json");

if ($contentIsJson === false){
    throw new Exception('Content type must be: application/json');
}

//Receive the RAW post data.
$content = trim(file_get_contents("php://input"));

//Attempt to decode the incoming RAW post data from JSON.
$decoded = json_decode($content, true);

$app = strtoupper($decoded['API']);
$key = $decoded['APIKEY'];

//verify user key - simple MD5 generator: http://onlinemd5.com/.  will build user management for keys if ever needed
if ( $key == "BEAF1CB722A3F7758C7A7FA43F6BF2D1" )
{   

    switch ($app) {
        case "TIME":
            $jsonString = getTime();
            $arr = array('datetime' => $jsonString);
            break;
        default:
            $arr = array('error' => "Unknown Request On API");
            break;
    }  

    echo json_encode($arr);
}


//return the current time
function getTime ()
{
    $DateTime = new DateTime();

    //by default heroku returns time in UTC - can change in dashboard, config vars, only use as needed below
    //$DateTime->modify('-6 hours');
    $currentTime = $DateTime->format("Y-m-d H:i:s");

    $jsonString = $currentTime;

    return $jsonString;
}

?>

 

Verifying the Response

I used Postman to send a raw JSON request to my Heroku app (used their default/free url).  I wanted to make sure all my problems were resolved with this new toy, first, and then move on.  Here’s what the raw request and response look like on Postman:

Heroku + my PHP are responding nicely!

Handling the Request and Response in C#

So here’s how I did the same request and received the response in C# (I use dotnet Core):

public async Task<string> OurHerokuAPI()
{
    string reqUrl = "https://mycompany-api.herokuapp.com";

    using (var client = new HttpClient())
    {
        client.DefaultRequestHeaders
            .Accept
            .Add(new MediaTypeWithQualityHeaderValue("application/json"));

        try
        {

            var query = new
            {
                APIKEY = "BEAF1CB722A3F7758C7A7FA43F6BF2D1",
                API = "time"
            };

            var asJson = JsonConvert.SerializeObject(query);
            HttpResponseMessage response = await client.PostAsync(reqUrl, new StringContent(asJson, Encoding.UTF8, "application/json"));

            if (response.IsSuccessStatusCode)
            {
                var definition = new { datetime = string.Empty };
                var json = JsonConvert.DeserializeAnonymousType(response.Content.ReadAsStringAsync().Result, definition);

                time = json.datetime;

                //monitors success across various "time" api's. in case this particular one fails, there can be various backups until success flag returns true.
                success = true;
            }
        }
        catch (OperationCanceledException)
        {
            //TODO: CREATE ERROR MESSAGE SEND BACK TO EMAIL/ERROR 
        }
    }
    return time;
}

 

If you see notes, yes, I decided to have some fun and create maybe two other functions, just like the one above, where I query some “free” time api’s until that “success” flag turns true.  After x tries, I reluctantly call my last function, that gets the server timestamp.  As said, I wanted my timestamp to be independent of server.  So, if it hits this last method, I also send myself an error email that the time API is failing.

In the future, I could  use environment variables (config vars) more wisely, instead of hardcoding.  There’s also so much clean up to do, but this was a very fun intro into Heroku!

Continue Reading

Print PDF’s on Azure Using an API and RazorLight (Update 1)

The API mentioned in my first tutorial got taken down and so I had to do some updates.  First, choose another 3rd party API.  I currently am trying out  HTML 2 PDF Rocket and modified my code a bit:

[HttpGet]
public async Task<FileStreamResult> PrintAsync(int id)
{
    InvoiceVM invoiceVM = new InvoiceVM();
    invoiceVM = invoiceRepository.Get(id);

    var engine = new RazorLightEngineBuilder()
      .UseFilesystemProject(_hostingEnvironment.WebRootPath + "\\pdf\\")
      .UseMemoryCachingProvider()
      .Build();

    var view = await engine.CompileRenderAsync("PDF.cshtml", invoiceVM);
    string apiKey = "xxxxxxxxxxxxxxxxxxxx";

    using (var client = new WebClient())
    {
        // Build the conversion options
        NameValueCollection options = new NameValueCollection();
        options.Add("apikey", apiKey);
        options.Add("value", view);
        options.Add("MarginLeft", "10");
        options.Add("MarginRight", "10");
        options.Add("MarginTop", "10");
        options.Add("MarginBottom", "10");
        options.Add("PageSize", "Letter");

        MemoryStream ms = new MemoryStream(client.UploadValues("http://api.html2pdfrocket.com/pdf", options));

        return new FileStreamResult(ms, "application/pdf");
    }
}

This is based directly off the HTML 2 Rocket documentation.  For the rest of the code see the first tutorial.

 

Continue Reading

Print PDF’s on Azure Using an API and RazorLight

The Problem

I recently had an issue with printing a report to PDF using Microsoft Reporting Service and a RDLC file, etc. Something similar to this. Unfortunately, it worked great in development, but refused to work once deployed into Azure. No matter what I did, I could not duck the GDI errors I kept getting, and apparently this continues through a line of various PDF exporting extensions, all of which rely on GDI for export. Turns out, I’m not alone in facing this problem and so, I decided to find a solution.

The Solution

My general idea was to use something to render my PDF view, send that view as one long html string to a free PDF microservice and get the PDF in return.

Continue Reading

PayTrace: 400 Bad Request For Declined Payment

TLDR:  post IS successful.  PayTrace, by design, returns a 400 error, which sets off exceptions in httpresponse.  Solution: catch the exception and then continue deserializing your response.

I coded a few weeks ago a .NET post to the PayTrace API which helps me demo and test payment by credit card using client side encryption.  The process more or less went like this:

  • Create demo account as a merchant on Paytrace
  • Download PEM key
  • On submit of form with credit card information, an imported PayTraceJS library encrypts the card number and csc code
  • Use the demo account’s username and password to submit a request for a token
  • Submit transaction (which includes encrypted info as well as other required fields) using token and await response

A successful http response returns a status code of 200.  I read it via stream, deserialize it using json into my CardResponse object (both successful and failure responses have the same design).  Everything went great until I began testing rejected cards.

Continue Reading