Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Website visitor counter showing up as "[object Object]"

I am trying to setup a view counter for the AWS #CloudResumeChallenge. I am following the instructions on these two youtube videos:

I am also using both of these gentlemen’s GitHub repos as references:

I have followed the video’s instructions, step-by-step; however, when I load my cloud resume at https://justinhenson.cloud/, the visitor counter is showing "[object Object]" and upon inspecting the element, the original line in my index.html file changes from this:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

<div id="visitors" class="visitors"> You are visitor number<span id="visits"></span><span id="loader" class="loader"></span></div>

To this:

<div id="visitors" class="visitors"> You are visitor number<span id="visits">[object Object]</span><span id="loader" class="loader" style="display: none;"></span></div><span id="visits">[object Object]</span><span id="loader" class="loader" style="display: none;"></span></div>

Also, as you can see in my scripts.js file below, I have pointed the pathway to the AWS API Gateway to trigger the lambda handler:

"use strict";

$(document).ready(() => {
    $.post('https://pl8h7bxm3j.execute-api.us-east-1.amazonaws.com/Prod/visit/')
    .done(visitor_counter => {
        $('#loader').hide();
        $('#visits').text(visitor_counter);
    })
    .fail(e => {
        console.log('Error');
        console.log(e);
    });
});

I have tested my API Gateway with the Postman app and it returns the count without error:

enter image description here

I followed both of the instructions in the videos by enabling the CORS policy in my lambda handler in the "app.py" file to be wide open to reduce complexity:

import json
import boto3

dynamodb = boto3.resource('dynamodb', region_name='us-east-1')

table = dynamodb.Table('resume-website-app-tbl')

def lambda_handler(event, context):
    response = table.get_item(
        Key = {
            'ID':'visits'
        }
    )
    
    visit_count = response['Item']['counter'] 
    visit_count = str(int(visit_count) + 1)
    
    response = table.put_item(
        Item = {
            'ID':'visits',
            'counter': visit_count
        }
    )

    return {
        'statusCode': 200,
        'headers': {
            'Access-Control-Allow-Headers': '*',
            'Access-Control-Allow-Origin': '*',
            'Access-Control-Allow-Methods': '*'
        },
        'body': json.dumps({'visit_count': visit_count})
    }

Below is my template.yaml file that I built with SAM that contains the configuration for my CloudFront Distribution under "MyDistribution" and the configuration for MyLambdaFunction:

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  cloud-resume

  Sample SAM Template for cloud-resume

# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 3

Resources:
  ResumeWebsite:
    Type: AWS::S3::Bucket
    Properties:
      AccessControl: PublicRead
      WebsiteConfiguration:
        IndexDocument: index.html 
      BucketName: justinhenson-cloud-resume-website

  MyRoute53Record:
    Type: "AWS::Route53::RecordSetGroup"
    Properties:
      HostedZoneId: Z01881203GO4SRLRJE2CO 
      RecordSets:
        - Name: justinhenson.cloud 
          Type: A
          AliasTarget:
            HostedZoneId: Z2FDTNDATAQYW2
            DNSName: !GetAtt MyDistribution.DomainName

  MyCertificate:
    Type: AWS::CertificateManager::Certificate
    Properties:
      DomainName: justinhenson.cloud 
      ValidationMethod: DNS

  MyDistribution:
    Type: "AWS::CloudFront::Distribution"
    Properties:
      DistributionConfig:
        ViewerCertificate:
            AcmCertificateArn: !Ref MyCertificate
            SslSupportMethod: sni-only
        Aliases: 
          - justinhenson.cloud
        DefaultCacheBehavior:
          ViewerProtocolPolicy: redirect-to-https
          TargetOriginId: justinhenson-cloud-resume-website.s3.us-east-1.amazonaws.com
          DefaultTTL: 0
          MinTTL: 0
          MaxTTL: 0
          ForwardedValues:
            QueryString: false
        Origins:
          - DomainName: justinhenson-cloud-resume-website.s3.us-east-1.amazonaws.com
            Id: justinhenson-cloud-resume-website.s3.us-east-1.amazonaws.com
            CustomOriginConfig:
              OriginProtocolPolicy: http-only
        Enabled: "true"
        DefaultRootObject: index.html

  BucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties: 
      PolicyDocument:
        Id: MyPolicy
        Version: 2012-10-17
        Statement:
          - Sid: PublicReadForGetBucketObjects
            Effect: Allow
            Principal: "*"
            Action: "s3:GetObject"
            Resource: !Join
              - ""
              - - "arn:aws:s3:::"
                - !Ref ResumeWebsite
                - /*
      Bucket: !Ref ResumeWebsite

  MyDynamoDBTable:
    Type: AWS::DynamoDB::Table
    Properties:
      TableName: resume-website-app-tbl
      BillingMode: PAY_PER_REQUEST
      AttributeDefinitions:
        - AttributeName: "ID"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "ID"
          KeyType: "HASH"

  MyLambdaFunction:
    Type: AWS::Serverless::Function
    Properties:
      Policies:
        - DynamoDBCrudPolicy:
            TableName: resume-website-app-tbl
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.9
      Architectures:
        - x86_64
      Events:
        Visits:
          Type: Api
          Properties:
            Path: /visit
            Method: post

  HelloWorldFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.9
      Architectures:
        - x86_64
      Events:
        HelloWorld:
          Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
          Properties:
            Path: /hello
            Method: get

Outputs:
  # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
  # Find out more about other implicit resources you can reference within SAM
  # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
  HelloWorldApi:
    Description: "API Gateway endpoint URL for Prod stage for Hello World function"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
  HelloWorldFunction:
    Description: "Hello World Lambda Function ARN"
    Value: !GetAtt HelloWorldFunction.Arn
  HelloWorldFunctionIamRole:
    Description: "Implicit IAM Role created for Hello World function"
    Value: !GetAtt HelloWorldFunctionRole.Arn

I sincerely appreciate any help anyone can offer in shedding some light on this issue. Thanks.

>Solution :

You are trying to put all HTTP response object to html, so you get [object Object]

$(document).ready(() => {
    $.post('https://pl8h7bxm3j.execute-api.us-east-1.amazonaws.com/Prod/visit/')
    .done(res => {
        $('#loader').hide();
        $('#visits').text(res.visit_count);
    })
    .fail(e => {
        console.log('Error');
        console.log(e);
    });
});
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading