MBP(はてな)

MacBook Pro,iPhone Xs,React

AWS Lambda Hello World、Feedly APIの呼び出し

Feedly APIAWS Lambdaから実行したいため)

以下のリンクを開き、Googleのhiroyuki12でログインして、developer access tokenを取得

feedly cloud | developer

リージョン us-east-1 で作成した

Lambda - CallFeedlyAPI - Configuration - environment variablesで設定

$ brew install go

$ mkdir ~/go
$ mkdir ~/go/src
$ mkdir ~/go/src/TestLambda
$ cd ~/go/src/TestLambda
$ go mod init

”(全角)を"(半角)に置き換え。handler.goとhello.go

$ GOOS=linux go build -o handler handler.go
$ zip function.zip handler

ログ出力の欄にHello Golang!!された。

2021/1 はじめてのGo言語でのAWS Lambdaの実装方法 - 株式会社クリエーション・ビュー

環境変数を追加
AWS Lambda 環境変数の使用 - AWS Lambda

AWS LambdaでFeedly APIの呼び出し
feedly Cloud APIでカスタムRSSリーダーを作る(Part2) - Glasses Dogの雑記

$ vi greeting/hello.go

//パッケージ名はディレクトリと同じものにする必要があります。
package greeting
import(
  "fmt"
  "net/http"
  "log"
  "os"
  "encoding/json"
)
type Collection struct {
    Feeds []Feed `json:"feeds"`
}

type Feed struct {
    FeedID string `json:"feedId"`
}

//他のディレクトリ(パッケージ)から呼び出される関数は大文字から始まる必要があります。
//意外と間違えやすいポイントなので注意しましょう。
func SayHello(){
        fmt.Println("Hello Golang!!")

    req, err := http.NewRequest(
        http.MethodGet, "https://cloud.feedly.com/v3/collections" , nil)

    if err != nil {
        log.Fatal(err)
    }

    req.Header.Add(
        "Authorization",
        fmt.Sprintf("OAuth %s", os.Getenv("FEEDLY_TOKEN")))

    res, err := (&http.Client{}).Do(req)
    if err != nil {
        log.Fatal(err)
    }

    var collections []Collection
    json.NewDecoder(res.Body).Decode(&collections)

    if err != nil {
        log.Fatal(err)
    }

    fmt.Println("collections")
    fmt.Println(collections)

    fmt.Println("end")
}

Stream API
feedly Cloud APIでカスタムRSSリーダーを作る(Part2) - Glasses Dogの雑記

$ vi greeting/hello.go

/パッケージ名はディレクトリと同じものにする必要があります。
package greeting
import(
  "fmt"
  "net/http"
  "log"
  "os"
  "encoding/json"
)
type Collection struct {
    Feeds []Feed `json:"feeds"`
}
type Feed struct {
    FeedID string `json:"feedId"`
}
type Stream struct {
    Items []Item `json:"items"`
}
type Item struct {
    ID       string   `json:"id"`
    Title    string   `json:"title"`
    OriginID string   `json:"originId"`
    Summary  Summary  `json:"summary"`
    Visual   Visual   `json:"visual"`
}
type Summary struct {
    Content string `json:"content"`
}
type Visual struct {
    URL string `json:"url"`
}

//他のディレクトリ(パッケージ)から呼び出される関数は大文字から始まる必要があります。
//意外と間違えやすいポイントなので注意しましょう。
func SayHello(){
  fmt.Println("Hello Golang!!")

  res := CallFeedlyAPI("https://cloud.feedly.com/v3/streams/contents?streamId=user/41ba84d4-d1f7-4772-88fd-c6c03a024401/category/It&unreadOnly=true")

  var stream Stream
  json.NewDecoder(res.Body).Decode(&stream)

  fmt.Println("stream")
  fmt.Println(stream)

  fmt.Println("end")
}

func CallFeedlyAPI(url string) *http.Response {

    req, err := http.NewRequest(
        http.MethodGet, url, nil)

    if err != nil {
        log.Fatal(err)
    }

    req.Header.Add(
        "Authorization",
        fmt.Sprintf("OAuth %s", os.Getenv("FEEDLY_TOKEN")))

    res, err := (&http.Client{}).Do(req)
    if err != nil {
        log.Fatal(err)
    }

    return res
}




AWS LambdaをREST API(API Gateway)で叩く」がうまくいかない
URL の呼び出しのリンクをクリックした時に、{"message":"Internal server error"}のみ表示される
{"message":"Missing Authentication Token"}のみ表示される

解決するには、$ vi handler.go してexcuteFunctionのreturnを変更する
Go+Lambdaで最速サーバレスチュートリアル - Qiita

変更後

package main
import(
        "github.com/aws/aws-lambda-go/events"
        "github.com/aws/aws-lambda-go/lambda"
        "TestLambda/greeting"
)
type Item struct {
    ID       string   `json:"id"`
    Title    string   `json:"title"`
    OriginID string   `json:"originId"`
    Summary  Summary  `json:"summary"`
    Visual   Visual   `json:"visual"`
}
type Summary struct {
    Content string `json:"content"`
}
type Visual struct {
    URL string `json:"url"`
}
type MyEvent struct {
        Name string `json:"What is your name?"`
        Age int     `json:"How old are you?"`
}
type MyResponse struct {
        body string `json:"Answer:"`
}

func excuteFunction(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error){
        greeting.SayHello()
    return events.APIGatewayProxyResponse{
        Body:       `hello handler.go`,
        StatusCode: 200,
    }, nil
}
func main(){
        lambda.Start(excuteFunction)
}

AWS LambdaをREST API(API Gateway)で叩く - Glasses Dogの雑記



feedly Cloud APIでカスタムRSSリーダーを作る(Part4) - Glasses Dogの雑記

helloAPIでは表示できた

API Gateway + LambdaでREST API開発を体験しよう [10分で完成編] - Qiita

hellpAPI - ステージ - default - /test - GET の URL呼び出しのリンクを開く


Feedly APIメモ - Qiita

1つ目のタイトルとURLをprintlnで表示
$ vi greeting/hello.go

type Item struct {
    ID       string   `json:"id"`
    Title    string   `json:"title"`
    OriginID string   `json:"originId"`
    Summary  Summary  `json:"summary"`
    Visual   Visual   `json:"visual"`
    Alternates []Alternate `json:"alternate"`
}
type Alternate struct {
    Href string `json:"href"`
}

//他のディレクトリ(パッケージ)から呼び出される関数は大文字から始まる必要があります。
//意外と間違えやすいポイントなので注意しましょう。
func SayHello() *[]Item {
  fmt.Println("Hello Golang!!")

  res := CallFeedlyAPI("https://cloud.feedly.com/v3/streams/contents?streamId=user/41ba84d4-d1f7-4772-88fd-c6c03a024401/category/It&unreadOnly=true")

  var stream Stream
  json.NewDecoder(res.Body).Decode(&stream)

  var items []Item
  items = append(items, stream.Items...)

  fmt.Println("stream start   =============================")
  fmt.Println(stream)
  fmt.Println("stream end5   =============================")

  fmt.Println("items[0].Title")
  fmt.Println(items[0].Title)
  fmt.Println("items[0].Visual.URL")
  fmt.Println(items[0].Visual.URL)
  fmt.Println("items[0].Alternates[0].Href")
  fmt.Println(items[0].Alternates[0].Href)

  fmt.Println("end")

  return &items
}


最終

ojichatをサーバーレスAPI化した | DevelopersIO

feedly Cloud APIでカスタムRSSリーダーを作る(Part3) - Glasses Dogの雑記

$ vi handler.go

package main
import( 
        "encoding/json"
        "github.com/aws/aws-lambda-go/events"
        "github.com/aws/aws-lambda-go/lambda"
        "TestLambda/greeting"
)
type Item struct {
    ID       string   `json:"id"`
    Title    string   `json:"title"`
    OriginID string   `json:"originId"`
    Summary  Summary  `json:"summary"`
    Visual   Visual   `json:"visual"`
}
type Summary struct {
    Content string `json:"content"`
}
type Visual struct {
    URL string `json:"url"`
}
type MyEvent struct {
        Name string `json:"What is your name?"`
        Age int     `json:"How old are you?"`
}
type MyResponse struct {
        body string `json:"Answer:"`
}

func excuteFunction(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error){
        res, err := greeting.SayHello()
        if err != nil {
                return events.APIGatewayProxyResponse{
                        Body:       err.Error(),
                        StatusCode: 500,
                }, err
        }

    jsonResult, _ := json.Marshal(res)

    return events.APIGatewayProxyResponse{
        //Body:       `hello handler.go`,
        Body:       string(jsonResult),
        StatusCode: 200,
    }, nil
}
func main(){
        lambda.Start(excuteFunction)
}

$ vi greeting/hello.go

//パッケージ名はディレクトリと同じものにする必要があります。
package greeting
import(
  "fmt"
  "net/http"
  "log"
  "os"
  "encoding/json"
)
type MyResponse struct {
        Items []Item   `json:"items"`
}
type Collection struct {
    Feeds []Feed `json:"feeds"`
}
type Feed struct {
    FeedID string `json:"feedId"`
}
type Stream struct {
    Items []Item `json:"items"`
}
type Item struct {
    ID       string   `json:"id"`
    Title    string   `json:"title"`
    OriginID string   `json:"originId"`
    Summary  Summary  `json:"summary"`
    Visual   Visual   `json:"visual"`
    Alternates []Alternate `json:"alternate"`
}
type Summary struct {
    Content string `json:"content"`
}
type Visual struct {
    URL string `json:"url"`
}
type Alternate struct {
    Href string `json:"href"`
}

//他のディレクトリ(パッケージ)から呼び出される関数は大文字から始まる必要があります。
//意外と間違えやすいポイントなので注意しましょう。
func SayHello() (MyResponse, error) {
  fmt.Println("Hello Golang!!")

  res := CallFeedlyAPI("https://cloud.feedly.com/v3/streams/contents?streamId=user/41ba84d4-d1f7-4772-88fd-c6c03a024401/category/It&unreadOnly=true")

  var stream Stream
  json.NewDecoder(res.Body).Decode(&stream)

  var items []Item
  items = append(items, stream.Items...)

  fmt.Println("stream start   =============================")
  fmt.Println(stream)
  fmt.Println("stream end5   =============================")

  fmt.Println("items[0].Title")
  fmt.Println(items[0].Title)
  fmt.Println("items[0].Visual.URL")
  fmt.Println(items[0].Visual.URL)
  fmt.Println("items[0].Alternates[0].Href")
  fmt.Println(items[0].Alternates[0].Href)

  fmt.Println("end")

//  return &items
  return MyResponse{Items: items}, nil
}

func CallFeedlyAPI(url string) *http.Response {

    req, err := http.NewRequest(
        http.MethodGet, url, nil)

    if err != nil {
        log.Fatal(err)
    }

    req.Header.Add(
        "Authorization",
        fmt.Sprintf("OAuth %s", os.Getenv("FEEDLY_TOKEN")))

    res, err := (&http.Client{}).Do(req)
    if err != nil {
        log.Fatal(err)
    }

    return res
}


ReactでAPI GatewayのURLからGETした時に、CORSエラーが出るので
lambdaに追加。
API GatewayのリソースのアクションメニューからCORSの有効化を選択。

[Go,Rust,React] AWS APIGatewayでもCORSがしたい - Qiita

$ vi handler.go

    headers := map[string]string{
        "Content-Type":                    "application/json",
        "Access-Control-Allow-Origin":     request.Headers["origin"], // こっちは小文字!
        "Access-Control-Allow-Methods":    "OPTIONS,POST,GET",
        "Access-Control-Allow-Headers":    "Origin,Authorization,Accept,X-Requested-With",
        "Access-Control-Allow-Credential": "true",
    }

    return events.APIGatewayProxyResponse{
        //Body:       `hello handler.go`,
        Body:       string(jsonResult),
        StatusCode: 200,
        Headers:    headers,
    }, nil


moment

日付(Date) - とほほのWWW入門


lambdaに引数を追加

Golangはじめて物語(APIGateway+Lambdaといっしょ編) - Qiita

handler.goのfunc excuteFunctionにrequestの引数を追加
名前がcontinuation(任意)の値をcontinuation(任意の名前の変数)にセットする
lambdaの画面のテストではなぜか、"body": "{\"items\":null}"になるが、
API GATEWAYのURLに引数を追加してsafariで開くとitemsのデータが表示される。
curlでも確認できる
$ curl 'https://u2r6yb4u30.execute-api.us-east-1.amazonaws.com/default/feedly?continuation=99999999999999' | jq | less

func excuteFunction(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error){
  var continuation              string
  var continuationIsNotNull     bool

  if len(request.QueryStringParameters) == 0 {
    continuation = "999999999998"  //引数がない時
  } else {
    if continuation, continuationIsNotNull = request.QueryStringParameters["continuation"]; !continuationIsNotNull {
      continuation = "999999999997"  //引数にcontinuationがない時、ある時はcontinuationに値がセットされる
    }
  }

URLに引数(continuation)をつける ?continuation=99999999999999
https://dummy.execute-api.us-east-1.amazonaws.com/default/feedly?continuation=99999999999999


categories(FEEDSの下にあるカテゴリ)一覧を取得 (idとlabelとcreatedのみ)

$ curl -H "Authorization: OAuth yourAccessTokenValueGoesHere" https://cloud.feedly.com/v3/categories | jq

How to get all unread items using Feedly API - Stack Overflow