使用Google日历和球拍Google套餐“遗失结束时间”

时间:2016-05-31 01:35:23

标签: json rest google-api google-calendar-api racket

我正在使用Google API Racket库来尝试更新Google日历。 (API不完整,所以我在我去的时候扩展它。)

我似乎无法使用events.insert put调用向日历添加事件。执行put的代码如下:

(define (insert-events calendar-id
                       event
                       #:token [t #f]
                       #:max-attendees [max-attendees #f]
                       #:send-notifications [send-notifications #f]
                       #:supports-attachments [supports-attachments #f])
  (json-api-post (string->url
                  (format
                   "https://www.googleapis.com/calendar/v3/calendars/~a/events"
                   (form-urlencoded-encode calendar-id)))
                  event
                  #:token t))


(define (json-api-post u b
                       #:token [t #f]
                       #:headers [headers '()])
  (define b* (jsexpr->bytes b))
  (let retry ([t t]
              [retry-counter 0])
    (parse-json-response
     (POST-string u b* (if t (cons (token->authorization-header t) headers) headers))
     retry
     t
     retry-counter)))

(define (POST-string u b headers)
  (port->string (post-pure-port u b headers)))

但是,无论我如何使用该呼叫,我总是会收到错误400,并显示消息:“Missing End Time”。我检查了this question以确保我正确地发送了我的请求。我似乎是。作为参考,我发送的JSON对象是:

{
 "end": {
  "dateTime": "2016-05-30T14:00:00-04:00"
 },
 "start": {
  "dateTime": "2016-05-30T13:00:00-04:00"
 }
}

另外,为了确保我正确访问了正确的密钥和日历ID,我为本地计算机设置了一个echo服务器,并将网址从google.com更改为localhost,我的回复似乎正常:

POST /<Calendar-Id-Redacted> HTTP/1.1
Host: localhost
User-Agent: Racket/6.5.0.5 (net/http-client)
Content-Length: 116
Authorization: Bearer <Key-Redacted>

{
 "end": {
  "dateTime": "2016-05-30T14:00:00-04:00"
 },
 "start": {
  "dateTime": "2016-05-30T13:00:00-04:00"
 }
}

我似乎正在做的一切都是正确的。即使我的Racket代码中存在错误,通过Google的开发人员Web控制台发送完全相同的JSON对象似乎也可以正常工作。那么为什么发送这个特定的POST不起作用呢?

1 个答案:

答案 0 :(得分:3)

关闭。但实际上,您在POST请求的headers字段中缺少一条重要数据。即,行:

Content-Type: application/json

让您的整个请求成为:

POST /<Calendar-Id-Redacted> HTTP/1.1
Host: localhost
User-Agent: Racket/6.5.0.5 (net/http-client)
Content-Length: 116
Authorization: Bearer <Key-Redacted>
Content-Type: application/json

{
 "end": {
  "dateTime": "2016-05-30T14:00:00-04:00"
 },
 "start": {
  "dateTime": "2016-05-30T13:00:00-04:00"
 }
}

出于某种原因,如果您错过了Google,Google不会给您一个很好的错误消息,但如果您有错误消息,Google会按照API调用。

当你在curl中运行命令时,可以更清楚地看到这一点,如果你像这样运行它(你有一个名为data.txt的文件中有你的json对象:

curl -X POST -d @data.txt https://www.googleapis.com/calendar/v3/calendars/<Calendar-Id-Redacted>/events --header 'Authorization: Bearer <Key-Redacted>'

它会失败。但是,如果您使用--header "Content-Type: application/json"添加标头,API将按预期工作:

curl -X POST -d @data.txt https://www.googleapis.com/calendar/v3/calendars/<Calendar-Id-Redacted>/events --header 'Authorization: Bearer <Key-Redacted>' --header "Content-Type: application/json"

将该标题添加到库中只需要对生成发布请求的函数进行一次修改:

(define (json-api-post u b
                       #:token [t #f]
                       #:headers [headers '("Content-Type: application/json")])
  ....)

除了我们修改了header字段以包含(默认情况下)包含字符串:"Content-Type: application/json"的列表之外,它与前一个完全相同。通过此更改,Google应接受您的API。 (请注意,还有许多其他方法可以修改标头功能,这只是一种简单的方法。)

总而言之,您的最终代码应该类似于:

(define (insert-events calendar-id
                       event
                       #:token [t #f]
                       #:max-attendees [max-attendees #f]
                       #:send-notifications [send-notifications #f]
                       #:supports-attachments [supports-attachments #f])
  (json-api-post (string->url
                  (format
                   "https://www.googleapis.com/calendar/v3/calendars/~a/events"
                   (form-urlencoded-encode calendar-id)))
                  event
                  #:token t))


(define (json-api-post u b
                       #:token [t #f]
                       #:headers [headers '("Content-Type: application/json")])
  (define b* (jsexpr->bytes b))
  (let retry ([t t]
              [retry-counter 0])
    (parse-json-response
     (POST-string u b* (if t (cons (token->authorization-header t) headers) headers))
     retry
     t
     retry-counter)))

(define (POST-string u b headers)
  (port->string (post-pure-port u b headers)))

希望有所帮助。