shari-sushi / V-Kara-Lists

Vカラ(Vtuber歌枠把握アプリ)
MIT License
18 stars 3 forks source link

リソースの考え方を取り入れる #216

Open shari-sushi opened 4 months ago

shari-sushi commented 4 months ago

→ ここからがお勉強ちょっと下のコメント


いろんなサービスのapi youtube, switch, [discord](), [slack](), niconico?(本家は閉鎖した?):

https://api.search.nicovideo.jp/api/v2/snapshot/video/contents/search?q=初音ミク&targets=tagsExact&fields=contentId,title,viewCounter,startTime,thumbnailUrl,lengthSeconds&filters[categoryTags][0]=VOCALOID&_sort=-viewCounter&_offset=0&_limit=3&_context=apitest`

とか格好つけてるけど、多分全部参考にならん。このアプリそんな複雑じゃないから… これだけちゃんと読みなって感じだろうな https://cloud.google.com/apis/design/resource_names?hl=ja

P I サービス名 コレクション ID リソース ID コレクション ID リソース ID
//storage.googleapis.com /buckets /bucket-id /objects /object-id
shari-sushi commented 4 months ago

先に勉強した結果を↓

routingのbefore, afteer

※before : v1、after : v2
※ #225, #188, #202 の結果、リソースそのものが変化した
※userについては微変化
```go func Routing(r *gin.Engine) { controller := controllers.NewController(dbInit()) ver := r.Group("/v1") { users := ver.Group("/users") { users.POST("/signup", controller.CreateUser) users.PUT("/login", controller.LogIn) users.PUT("/logout", controllers.Logout) users.DELETE("/withdraw", controller.LogicalDeleteUser) users.GET("/gestlogin", controllers.GuestLogIn) users.GET("/profile", controller.GetListenerProfile) users.GET("/mypage", controller.ListenerPage) } vcontents := ver.Group("/vcontents") { vcontents.GET("/", controller.ReturnTopPageData) vcontents.GET("/vtuber/:kana", controller.ReturnVtuberPageData) // TODO : v2 : 単数形に vcontents.GET("/sings", controller.GetJoinVtubersMoviesKaraokes) vcontents.GET("/original-song", controller.ReturnOriginalSongPage) // /vtuber, /movie, /karaokeの文字列はフロント側で比較演算に使われてる // データ新規登録 vcontents.POST("/create/vtuber", controller.CreateVtuber) vcontents.POST("/create/movie", controller.CreateMovie) vcontents.POST("/create/karaoke", controller.CreateKaraoke) //データ編集 vcontents.POST("/edit/vtuber", controller.EditVtuber) vcontents.POST("/edit/movie", controller.EditMovie) vcontents.POST("/edit/karaoke", controller.EditKaraoke) // // データ削除(物理) vcontents.GET("/delete/deletePage", controller.DeleteOfPage) vcontents.DELETE("/delete/vtuber", controller.DeleteVtuber) vcontents.DELETE("/delete/movie", controller.DeleteMovie) vcontents.DELETE("/delete/karaoke", controller.DeleteKaraoke) //ドロップダウン用 vcontents.GET("/getalldata", controller.GetVtuverMovieKaraoke) // テスト用 vcontents.GET("/dummy-top-page", controller.ReturnDummyTopPage) } fav := ver.Group("/fav") { fav.POST("/favorite/movie", controller.SaveMovieFavorite) fav.DELETE("/unfavorite/movie", controller.DeleteMovieFavorite) fav.POST("/favorite/karaoke", controller.SaveKaraokeFavorite) fav.DELETE("/unfavorite/karaoke", controller.DeleteKaraokeFavorite) } } var v2 = r.Group("/v2") { users := ver.Group("/users") { users.GET("/login", controller.LogIn) //GETに変えた注意 users.GET("/logout", controllers.Logout) //GETに変えた注意 users.POST("/signup", controller.CreateUser) users.DELETE("/withdraw", controller.LogicalDeleteUser) //softDeleteに改名したいです users.GET("/guest", controllers.GuestLogIn) //guestの綴り修正した注意 users.GET("/profile", controller.GetListenerProfile) users.GET("/favorite", func(c *gin.Context) {}) } vtubers := v2.Group("/vtubers") { vtubers.GET("/", func(c *gin.Context) {}) vtubers.POST("/create", func(c *gin.Context) {}) vtubers.PUT("/update", func(c *gin.Context) {}) vtubers.DELETE("/delete", func(c *gin.Context) {}) vtubers.POST("/favorite", func(c *gin.Context) {}) vtubers.DELETE("/unfavorite", func(c *gin.Context) {}) } movies := v2.Group("/movies") { singleSong := movies.Group("/single-song") { singleSong.GET("/", func(c *gin.Context) {}) singleSong.POST("/create", func(c *gin.Context) {}) singleSong.PUT("/update", func(c *gin.Context) {}) singleSong.DELETE("/delete", func(c *gin.Context) {}) singleSong.POST("/favorite", func(c *gin.Context) {}) singleSong.DELETE("/unfavorite", func(c *gin.Context) {}) } multipleSongs := movies.Group("/multiple-songs") { multipleSongs.GET("/", func(c *gin.Context) {}) multipleSongs.POST("/create", func(c *gin.Context) {}) multipleSongs.PUT("/update", func(c *gin.Context) {}) multipleSongs.DELETE("/delete", func(c *gin.Context) {}) multipleSongs.POST("/favorite", func(c *gin.Context) {}) multipleSongs.DELETE("/unfavorite", func(c *gin.Context) {}) } } } } ```

こんなんかなぁ

shari-sushi commented 4 months ago

RESET APIであればこっちの方が分かりやすい(あと、ダークモードなので読みやすい) microsoft RESTful Web API の設計

エンティティはコレクションにグループ化される。

// ordersコレクションのgetリクエストuriである。
https://adventure-works.com/orders

// No. 5の顧客の注文に対するgetリクエスト?
/customers/5/orders

ヒント "コレクション/項目/コレクション" よりも複雑なリソース URI を要求しないでください。

クエリ

クエリ文字列を使用して必要なパラメーターを指定する URI を提供できます。 たとえば、URI /add?operand1=99&operand2=1 への GET リクエストは、値 100 を含む本文を持つ応答メッセージを返します。 ただし、これらの形式の URI は常に慎重に使用してください。

現状、api側でlimit 50を指定している。しかし、クエリを使うようにすれば柔軟にできる。 (limitの数を変えるときapp側を変更するだけで済むし、複数のlimitの数に対応できる。)

shari-sushi commented 4 months ago

HTTP メソッド


  • GET: 指定した URI のリソースの表現を取得します。 応答メッセージの本文には、要求されたリソースの詳細が含まれています。
  • POST: 指定した URI の新しいリソースを作成します。 応答メッセージの本文には、新しいリソースの詳細が記載されています。 POST は実際にはリソースを作成しない操作をトリガーするのにも使用できます。
  • PUT: 指定した URI のリソースを作成または置換します。 要求メッセージの本文で、作成または更新するリソースを指定します。
  • PATCH: リソースの部分的な更新を実行します。 要求本文でリソースに適用する一連の変更を指定します。
  • DELETE: 指定した URI のリソースを削除します。

結構適当に、PUTもPATCHもPOSTに集約させてたからな…。 ってか、PUTを今やっと理解した。 冪等になるってそういうことか、結果が同じだから、updateクエリについてはそうだよね。 insertクエリだとデータが増えるもんね(uniqueでなければ)。 なるほどね!! 良く分からなくてずっとPOSTにしてたわ。

また、POSTについての

応答メッセージの本文には、新しいリソースの詳細が記載されています

もやってなかったからなぁ。

respons status

POSTの成功は201とか全然知らなかった

JSON が Web API の最も一般的なデータ形式と考えられます。 主な JSON ベースのパッチ形式として、JSON パッチと JSON マージ パッチの 2 つがあります。