brendanhay / gogol

A comprehensive Google Services SDK for Haskell.
Other
281 stars 105 forks source link

Translate API: Works in wget but not here #137

Open danwdart opened 5 years ago

danwdart commented 5 years ago

I've got a translate request with trace:

[Client Request] {
  host      = translation.googleapis.com:443
  secure    = True
  method    = POST
  timeout   = ResponseTimeoutMicro 70000000
  redirects = 10
  path      = /language/translate/v2
  query     = ?pp=true&alt=json
  headers   = authorization: Bearer BLAH BLAH BLAH; accept: application/json;charset=utf-8; content-type: application/json;charset=utf-8
  body      = {"format":"text","q":["hallo"],"model":"nmt","source":"de","target":"en"}
}
[Client Response] {
  status  = 200 OK
  headers = content-type: application/json; charset=UTF-8; vary: Origin; vary: X-Origin; vary: Referer; content-encoding: gzip; date: Sun, 28 Jul 2019 11:37:19 GMT; server: ESF; cache-control: private; x-xss-protection: 0; x-frame-options: SAMEORIGIN; x-content-type-options: nosniff; alt-svc: quic=":443"; ma=2592000; v="46,43,39"; transfer-encoding: chunked
}

however it doesn't actually save anything into the variable: TranslationsListResponse' {_tlrTranslations = Nothing}

Credentials are all good, I tried in wget and browser console and it was fine and returned proper response, but using this is just a response of Nothing...

Code:

{-# LANGUAGE OverloadedStrings, TemplateHaskell #-}

import Control.Monad
import Control.Lens
import Data.Function
import Data.Text
import Network.Google
import Network.Google.Translate
import System.Environment
import System.IO

main :: IO ()
main = do
    lgr <- newLogger Trace stdout
    setEnv "GOOGLE_APPLICATION_CREDENTIALS" "./google.json"
    env <- newEnv <&> (envLogger .~ lgr) . (envScopes .~ cloudTranslationScope)
    a <- runResourceT . runGoogle env $ send myR
    print $ a^.tlrTranslations

myT :: TranslateTextRequest
myT = translateTextRequest & ttrFormat .~ Just "text" & ttrQ .~ ["hallo"] & ttrSource .~ (Just "de") & ttrTarget .~ (Just "en") & ttrModel .~ (Just "nmt")

myR :: TranslationsTranslate
myR = myT & translationsTranslate & ttPp .~ True

Thanks

andorp commented 5 years ago

Same for me.

andorp commented 5 years ago

I found the root cause:

The response JSON seems to have an extra "data" tag:

body      = {"q":["Dursleys were proud to say that they were perfectly normal."],"source":"en","target":"es"}
}
[Client Response] {
  status  = 200 OK
  headers = content-type: application/json; charset=UTF-8; vary: Origin; vary: X-Origin; vary: Referer; content-encoding: gzip; date: Tue, 27 Aug 2019 22:38:59 GMT; server: ESF; cache-control: private; x-xss-protection: 0; x-frame-options: SAMEORIGIN; x-content-type-options: nosniff; alt-svc: quic=":443"; ma=2592000; v="46,43,39"; transfer-encoding: chunked
}
Object (fromList [("data",Object (fromList [("translations",Array [Object (fromList [("translatedText",String "Los Dursley estaban orgullosos de decir que eran perfectamente normales.")])])]))])

I made a monkey patch in the gogol-translate:

instance FromJSON TranslationsListResponse where
  parseJSON =
    withObject "" (\o1 -> do
      x <- o1 .: "data"
      withObject "" (\o ->
         TranslationsListResponse' <$>
           (o .:? "translations" .!= mempty)
        )
        x)

@brendanhay What is the best way to actually implement this fix in the gogol framework? I am happy to do the legwork, but I need some guidance.