我遇到了一个奇怪的问题,在这个问题中,我无法对一个基于graphql而无法控制的rest服务执行简单的post请求。
问题是,不管我在httpMethod类的URLRequest属性中设置了什么,它总是使用GET来代替。
我做了一些测试来排除一些问题。例如,我在请求中设置了一个头,我可以验证该头是否被发送到服务器(使用charles proxy验证)。
这是可以在操场上粘贴和运行的代码:

import PlaygroundSupport
import Foundation
PlaygroundPage.current.needsIndefiniteExecution = true

let url = URL(string: "http://graphql.anilist.co/")!
let internalSession = URLSession(configuration: .default)
var request = URLRequest(url: url)
request.httpMethod = "POST"
let headers = ["content-type": "application/json"]
request.allHTTPHeaderFields = headers
request.httpBody =
"""
{"query":"query (\n\t$season: MediaSeason,\n\t$year: Int,\n\t$format: MediaFormat,\n\t$excludeFormat: MediaFormat,\n\t$status: MediaStatus,\n\t$minEpisodes: Int,\n\t$page: Int,\n){\n\tPage(page: $page) {\n\t\tpageInfo {\n\t\t\thasNextPage\n\t\t\ttotal\n\t\t}\n\t\tmedia(\n\t\t\tseason: $season\n\t\t\tseasonYear: $year\n\t\t\tformat: $format,\n\t\t\tformat_not: $excludeFormat,\n\t\t\tstatus: $status,\n\t\t\tepisodes_greater: $minEpisodes,\n\t\t\tisAdult: false,\n\t\t\ttype: ANIME,\n\t\t\tsort: TITLE_ROMAJI,\n\t\t) {\n\t\t\t\nid\nidMal\ntitle {\n\tromaji\n\tnative\n\tenglish\n}\nstartDate {\n\tyear\n\tmonth\n\tday\n}\nendDate {\n\tyear\n\tmonth\n\tday\n}\nstatus\nseason\nformat\ngenres\nsynonyms\nduration\npopularity\nepisodes\nsource(version: 2)\ncountryOfOrigin\nhashtag\naverageScore\nsiteUrl\ndescription\nbannerImage\ncoverImage {\n\textraLarge\n\tcolor\n}\ntrailer {\n\tid\n\tsite\n\tthumbnail\n}\nexternalLinks {\n\tsite\n\turl\n}\nrankings {\n\trank\n\ttype\n\tseason\n\tallTime\n}\nstudios(isMain: true) {\n\tnodes {\n\t\tid\n\t\tname\n\t\tsiteUrl\n\t}\n}\nrelations {\n\tedges {\n\t\trelationType(version: 2)\n\t\tnode {\n\t\t\tid\n\t\t\ttitle {\n\t\t\t\tromaji\n\t\t\t\tnative\n\t\t\t\tenglish\n\t\t\t}\n\t\t\tsiteUrl\n\t\t}\n\t}\n}\n\nairingSchedule(\n\tnotYetAired: true\n\tperPage: 2\n) {\n\tnodes {\n\t\tepisode\n\t\tairingAt\n\t}\n}\n\n\t\t}\n\t}\n}","variables":{"season": WINTER,"year": 2019,"page": 1, "perPage": 100}}
""".data(using: .utf8)
print("THE REQUEST \(String(describing: request.httpMethod))")
let task = internalSession.dataTask(with: request, completionHandler: { (data, response, error) in
    if let e = error {
        print("ERROR: \(e)")
    } else if let response = response as? HTTPURLResponse {
        print("THE RESPONSE: \(response)")
        let json = try! JSONSerialization.jsonObject(with: data!, options: [])
        print(json)
    }
})
task.resume()


(请忽略所有强制展开选项并强制try!,这是测试代码)。
预期结果
我希望web服务返回类似于以下内容的json(简化):
{
    "data": {
        "Page": {
            "pageInfo": {
                "hasNextPage": true,
                "total": 81
            },
            "media": [
                {
                    "id": 102882,
                    "idMal": 37956,
                    "title": {
                        "romaji": "3D Kanojo: Real Girl 2",
                        "native": "3D彼女 リアルガール 2",
                        "english": "Real Girl 2"
                    },
                    "startDate": {
                        "year": 2019,
                        "month": 1,
                        "day": 9
                    },
                    "endDate": {
                        "year": null,
                        "month": null,
                        "day": null
                    },
                    "status": "RELEASING",
                    "season": "WINTER",
                    "format": "TV",
                    "genres": [
                        "Romance",
                        "Slice of Life",
                        "Comedy"
                    ],
                    "synonyms": [],
                    "duration": 23,
                    "popularity": 3298,
                    "episodes": 12,
                    "source": "MANGA",
                    "countryOfOrigin": "JP",
                    "hashtag": "#3D彼女リアルガール #3D彼女",
                    "averageScore": 61,
                    "siteUrl": "https://anilist.co/anime/102882",
                    "description": "The second season of <i>3D Kanojo</i>.",
                    "bannerImage": null,
                    "coverImage": {
                        "extraLarge": "https://s4.anilist.co/file/anilistcdn/media/anime/cover/large/nx102882-lKp3ExWNzoE6.jpg",
                        "color": "#e4bb93"
                    },
                    "trailer": {
                        "id": "x6yokzp",
                        "site": "dailymotion",
                        "thumbnail": "https://www.dailymotion.com/thumbnail/video/x6yokzp"
                    },
                    "externalLinks": [
                        {
                            "site": "Official Site",
                            "url": "http://www.3dkanojo-anime.com/"
                        },
                        {
                            "site": "Twitter",
                            "url": "https://twitter.com/3Dkanojo_anime"
                        }
                    ],
                    "rankings": [
                        {
                            "rank": 16,
                            "type": "RATED",
                            "season": null,
                            "allTime": false
                        },
                        {
                            "rank": 19,
                            "type": "POPULAR",
                            "season": null,
                            "allTime": false
                        },
                        {
                            "rank": 16,
                            "type": "RATED",
                            "season": "WINTER",
                            "allTime": false
                        },
                        {
                            "rank": 15,
                            "type": "POPULAR",
                            "season": "WINTER",
                            "allTime": false
                        }
                    ],
                    "studios": {
                        "nodes": [
                            {
                                "id": 346,
                                "name": "Hoods Entertainment",
                                "siteUrl": "https://anilist.co/studio/346"
                            }
                        ]
                    },
                    "relations": {
                        "edges": [
                            {
                                "relationType": "PREQUEL",
                                "node": {
                                    "id": 100526,
                                    "title": {
                                        "romaji": "3D Kanojo: Real Girl",
                                        "native": "3D彼女 リアルガール",
                                        "english": "Real Girl"
                                    },
                                    "siteUrl": "https://anilist.co/anime/100526"
                                }
                            },
                            {
                                "relationType": "SOURCE",
                                "node": {
                                    "id": 80767,
                                    "title": {
                                        "romaji": "3D Kanojo: Real Girl",
                                        "native": "3D彼女 〈リアルガール〉",
                                        "english": "Real Girl"
                                    },
                                    "siteUrl": "https://anilist.co/manga/80767"
                                }
                            }
                        ]
                    },
                    "airingSchedule": {
                        "nodes": [
                            {
                                "episode": 7,
                                "airingAt": 1550595540
                            },
                            {
                                "episode": 8,
                                "airingAt": 1551200340
                            }
                        ]
                    }
                }
            ]
        }
    }
}

获得的结果
相反,我知道:
{
    "data": null,
    "errors": [
        {
            "message": "Not Found.",
            "hint": "Use POST request to access graphql subdomain.",
            "status": 404
        }
    ]
}

服务抱怨请求是get请求,应该是post,我明确告诉urlrequest使用post。如果您在charles或其他代理中查看请求,您将确实看到请求是作为get请求执行的,并且httpBody属性被丢弃。如果编辑标题并添加另一个标题,如下所示:
let headers = ["content-type": "application/json", "foo": "bar"]

您将在代理服务器中看到正确发送头。
我能得出的唯一结论是,URLSessionDataTask存在一个内部问题,迫使只执行get请求。我试着把它改成下载任务,但同样的问题也在发生。所以我的代码肯定有问题,但我找不到。
编辑:
根据请求,这是邮递员使用的请求。我已将请求导出到curl,以使其易于导入。
curl -X POST \
  https://graphql.anilist.co/ \
  -H 'Content-Type: application/json' \
  -H 'Postman-Token: 49d7e55e-35c2-4a3c-82f0-4eccb1250fc0' \
  -H 'cache-control: no-cache' \
  -d '{"query":"query (\n\t$season: MediaSeason,\n\t$year: Int,\n\t$format: MediaFormat,\n\t$excludeFormat: MediaFormat,\n\t$status: MediaStatus,\n\t$minEpisodes: Int,\n\t$page: Int,\n){\n\tPage(page: $page) {\n\t\tpageInfo {\n\t\t\thasNextPage\n\t\t\ttotal\n\t\t}\n\t\tmedia(\n\t\t\tseason: $season\n\t\t\tseasonYear: $year\n\t\t\tformat: $format,\n\t\t\tformat_not: $excludeFormat,\n\t\t\tstatus: $status,\n\t\t\tepisodes_greater: $minEpisodes,\n\t\t\tisAdult: false,\n\t\t\ttype: ANIME,\n\t\t\tsort: TITLE_ROMAJI,\n\t\t) {\n\t\t\t\nid\nidMal\ntitle {\n\tromaji\n\tnative\n\tenglish\n}\nstartDate {\n\tyear\n\tmonth\n\tday\n}\nendDate {\n\tyear\n\tmonth\n\tday\n}\nstatus\nseason\nformat\ngenres\nsynonyms\nduration\npopularity\nepisodes\nsource(version: 2)\ncountryOfOrigin\nhashtag\naverageScore\nsiteUrl\ndescription\nbannerImage\ncoverImage {\n\textraLarge\n\tcolor\n}\ntrailer {\n\tid\n\tsite\n\tthumbnail\n}\nexternalLinks {\n\tsite\n\turl\n}\nrankings {\n\trank\n\ttype\n\tseason\n\tallTime\n}\nstudios(isMain: true) {\n\tnodes {\n\t\tid\n\t\tname\n\t\tsiteUrl\n\t}\n}\nrelations {\n\tedges {\n\t\trelationType(version: 2)\n\t\tnode {\n\t\t\tid\n\t\t\ttitle {\n\t\t\t\tromaji\n\t\t\t\tnative\n\t\t\t\tenglish\n\t\t\t}\n\t\t\tsiteUrl\n\t\t}\n\t}\n}\n\nairingSchedule(\n\tnotYetAired: true\n\tperPage: 2\n) {\n\tnodes {\n\t\tepisode\n\t\tairingAt\n\t}\n}\n\n\t\t}\n\t}\n}","variables":{"year":2019,"season":"WINTER","page":1, "limit": 12}}'

最佳答案

我在这里看到的唯一区别是在你的操场和邮递员。
所以在你的http://中用https://替换http://

关于swift - URLSessionDataTask忽略URLRequest的httpMethod属性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54715318/

10-11 15:02