Categorygithub.com/GnarlyLasagna/go-blog-aggregator
repositorypackage
0.0.0-20240306183722-fd4d1c25798b
Repository: https://github.com/gnarlylasagna/go-blog-aggregator.git
Documentation: pkg.go.dev

# README

go-blog-aggregator

This is a guided project in Go from boot.dev where you make a webserver rss posts scrapper.

Features

Fetches and parses RSS feeds.
Stores feed content in PostgreSQL.
Displays content using the Chi web framework.

Getting Started

Clone the repository:

git clone https://github.com/....

You will need to create a postgres database and create a .env file like this one:

PORT="8080"
CONN="postgres://user:password@host:port/database?sslmode=disable"

For executing migrations I used goose while in ./sql/schema/:

goose postgres postgres://user:password@host:port/database up

or in the root dir:

goose -dir ./sql/schema postgres postgres://user:password@host:port/database up

Finally run the app:

go build && ./go-blog-aggregator

Access the aggregator at http://localhost:8080.

Endpoints

GET /v1/readiness:

I made this endpoint to test RespondWithJSON. Response example:

{
  "status": "ok"
}

GET /v1/err:

I made this endpoint to test RespondWithError. Response example:

{
  "error": "Internal Server Error"
}

POST /v1/users:

Creates an user and returns it's information and the ApiKey used for future authorization.

Body example:

{
  "name": "YourName"
}

Response example:

{
  "id": "093cce59-51bb-41ad-aa2a-22b678c8baac",
  "created_at": "2024-02-13T16:17:57.203873Z",
  "updated_at": "2024-02-13T16:17:57.203873Z",
  "name": "YourName",
  "api_key": "8c3e80fcc8daca693290ca993ce8ded0a11317044918408f963d8bee6acdc9b1"
}

GET /v1/users:

Returns information about user authenticated by ApiKey.

Authentication: Bearer Token

Authorization: ApiKey YourAPIKey

Response example:

{
  "id": "093cce59-51bb-41ad-aa2a-22b678c8baac",
  "created_at": "2024-02-13T16:17:57.203873Z",
  "updated_at": "2024-02-13T16:17:57.203873Z",
  "name": "YourName",
  "api_key": "8c3e80fcc8daca693290ca993ce8ded0a11317044918408f963d8bee6acdc9b1"
}

POST /v1/feed:

Creates a new feed.

Authentication: Bearer Token

Authorization: ApiKey YourAPIKey

Body example:

{
  "name": "Feed name",
  "url": "urlofthefeed.com"
}

Response example:

{
  "feed": {
    "id": "900c5010-7885-48a7-9ed0-f20466eb76ff",
    "name": "Feed name",
    "url": "urlofthefeed.com",
    "user_id": "5347d2c0-b6b9-4317-8119-b970066e6ead",
    "created_at": "2024-02-13T16:25:03.656305Z",
    "updated_at": "2024-02-13T16:25:03.656305Z",
    "last_updated_at": {
      "Time": "0001-01-01T00:00:00Z",
      "Valid": false
    }
  },
  "feed_follow": {
    "id": "b3017f76-6725-4e05-a731-6c93cefd3f80",
    "feed_id": "900c5010-7885-48a7-9ed0-f20466eb76ff",
    "user_id": "5347d2c0-b6b9-4317-8119-b970066e6ead",
    "created_at": "2024-02-13T16:25:03.660531Z",
    "updated_at": "2024-02-13T16:25:03.660531Z"
  }
}

GET /v1/feeds:

Returns all feeds.

Response example:

[
  {
    "id": "741d3546-51bc-42a9-9d1d-58f28b0a40cf",
    "name": "Amazing random feed",
    "url": "https://amazingrandomfeed.com/",
    "user_id": "5347d2c0-b6b9-4317-8119-b970066e6ead",
    "created_at": "2024-02-11T17:06:53.130634Z",
    "updated_at": "2024-02-13T16:25:33.438107Z",
    "last_updated_at": {
      "Time": "2024-02-13T16:25:33.438107Z",
      "Valid": true
    }
  },
  {
    "id": "900c5010-7885-48a7-9ed0-f20466eb76ff",
    "name": "Feed name",
    "url": "urlofthefeed.com",
    "user_id": "5347d2c0-b6b9-4317-8119-b970066e6ead",
    "created_at": "2024-02-13T16:25:03.656305Z",
    "updated_at": "2024-02-13T16:25:33.43813Z",
    "last_updated_at": {
      "Time": "2024-02-13T16:25:33.43813Z",
      "Valid": true
    }
  },
  {
    "id": "ab6b65f3-a66f-48fb-8852-6a25c014697f",
    "name": "Another random feed",
    "url": "https://anotherrandomfeed.com/index.xml",
    "user_id": "5347d2c0-b6b9-4317-8119-b970066e6ead",
    "created_at": "2024-02-10T22:34:44.652131Z",
    "updated_at": "2024-02-13T16:25:33.441105Z",
    "last_updated_at": {
      "Time": "2024-02-13T16:25:33.441105Z",
      "Valid": true
    }
  }
]

POST /v1/feed_follows:

Follows an existing feed.

Authentication: Bearer Token

Authorization: ApiKey YourAPIKey

Body example:

{
  "feed_id": "ab6b65f3-a66f-48fb-8852-6a25c014697f"
}

Response example:

{
  "id": "20635fe9-c339-4c93-8df4-a798de671cc7",
  "feed_id": "ab6b65f3-a66f-48fb-8852-6a25c014697f",
  "user_id": "093cce59-51bb-41ad-aa2a-22b678c8baac",
  "created_at": "2024-02-13T16:34:49.747039Z",
  "updated_at": "2024-02-13T16:34:49.747039Z"
}

DELETE /v1/feed_follows/{feedFollowID}:

Deletes a feed_follows by feedFollowID.

Authentication: Bearer Token

Authorization: ApiKey YourAPIKey

GET /v1/feed_follows:

Return every feed follow of the user.

Authentication: Bearer Token

Authorization: ApiKey YourAPIKey

Response example:

[
  {
    "id": "f84075a2-9325-4ef3-b4c2-739b34731658",
    "feed_id": "741d3546-51bc-42a9-9d1d-58f28b0a40cf",
    "user_id": "5347d2c0-b6b9-4317-8119-b970066e6ead",
    "created_at": "2024-02-11T17:06:53.136533Z",
    "updated_at": "2024-02-11T17:06:53.136533Z"
  },
  {
    "id": "b3017f76-6725-4e05-a731-6c93cefd3f80",
    "feed_id": "900c5010-7885-48a7-9ed0-f20466eb76ff",
    "user_id": "5347d2c0-b6b9-4317-8119-b970066e6ead",
    "created_at": "2024-02-13T16:25:03.660531Z",
    "updated_at": "2024-02-13T16:25:03.660531Z"
  }
]

GET /v1/posts:

Return posts of the user feed.

Authentication: Bearer Token

Authorization: ApiKey YourAPIKey

Body example:

{
  "limit": 2
}

Response example:

[
  {
    "id": "04373594-bd87-4ca8-8fb0-fc5479a4642d",
    "created_at": "2024-02-13T14:31:39.90568Z",
    "updated_at": "2024-02-13T14:31:39.90568Z",
    "title": "RandomTitle",
    "url": "https://randomfeed.com/randomTitle/",
    "description": {
      "String": "\n      \n      \n      \n      \n      \n      \n    ",
      "Valid": true
    },
    "published_at": {
      "Time": "2024-01-28T00:00:00Z",
      "Valid": true
    },
    "feed_id": "ab6b65f3-a66f-48fb-8852-6a25c014697f"
  },
  {
    "id": "952a783e-f980-454c-896a-b883f3ef8623",
    "created_at": "2024-02-13T14:31:39.900174Z",
    "updated_at": "2024-02-13T14:31:39.900174Z",
    "title": "second random title",
    "url": "https://secondrandomfeed.com/title",
    "description": {
      "String": "\n      \n      \n      \n      \n      \n      \n    ",
      "Valid": true
    },
    "published_at": {
      "Time": "2024-01-31T00:00:00Z",
      "Valid": true
    },
    "feed_id": "ab6b65f3-a66f-48fb-8852-6a25c014697f"
  }
]