New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initial implementation of go-translate #1
Changes from 1 commit
63c8536
40bc6b7
58049eb
0ebeb8d
e1dde00
711e789
8ebc725
7aed697
e1766c0
d8129d4
1cf4eaf
81590b7
f6c165b
2c154d7
File filter...
Jump to…
Add language endpoint for get language list requests
- Loading branch information
| @@ -7,6 +7,7 @@ import ( | ||
| "net/http" | ||
| "time" | ||
|
|
||
| "github.com/brave/go-translate/language" | ||
| "github.com/brave/go-translate/translate" | ||
| "github.com/go-chi/chi" | ||
| log "github.com/sirupsen/logrus" | ||
| @@ -16,11 +17,20 @@ import ( | ||
| // brave-core, and it can be set to other hosts during testing. | ||
| var MSTranslateServer = "https://api.cognitive.microsofttranslator.com" | ||
|
|
||
|
|
||
| const ( | ||
| languageEndpoint = "/languages?api-version=3.0&scope=translation" | ||
| ) | ||
|
|
||
| // TranslateRouter add routers for translate requests and translate script | ||
| // requests. | ||
| func TranslateRouter() chi.Router { | ||
| r := chi.NewRouter() | ||
|
|
||
| r.Post("/translate", Translate) | ||
| r.Get("/language", GetLanguageList) | ||
|
|
||
|
|
||
| return r | ||
| } | ||
|
|
||
| @@ -30,6 +40,57 @@ func getHTTPClient() *http.Client { | ||
| } | ||
| } | ||
|
|
||
| // GetLanguageList send a request to Microsoft server and convert the response | ||
| // into google format and reply back to the client. | ||
| func GetLanguageList(w http.ResponseWriter, r *http.Request) { | ||
| // Send a get language list request to MS | ||
| req, err := http.NewRequest("GET", MSTranslateServer+languageEndpoint, nil) | ||
|
This conversation was marked as resolved
by yrliou
evq
Member
|
||
| if err != nil { | ||
| http.Error(w, fmt.Sprintf("Error creating MS request: %v", err), http.StatusInternalServerError) | ||
|
This conversation was marked as resolved
by yrliou
|
||
| } | ||
|
|
||
| client := getHTTPClient() | ||
| msResp, err := client.Do(req) | ||
| if err != nil { | ||
| http.Error(w, fmt.Sprintf("Error sending request to MS server: %v", err), http.StatusInternalServerError) | ||
| return | ||
| } | ||
| defer func() { | ||
| err := msResp.Body.Close() | ||
| if err != nil { | ||
| log.Errorf("Error closing response body stream: %v", err) | ||
| } | ||
| }() | ||
|
|
||
| // Set response header | ||
| w.Header().Set("Content-Type", msResp.Header["Content-Type"][0]) | ||
| w.WriteHeader(msResp.StatusCode) | ||
|
|
||
| // Copy resonse body if status is not OK | ||
| if msResp.StatusCode != http.StatusOK { | ||
| _, err = io.Copy(w, msResp.Body) | ||
| if err != nil { | ||
| http.Error(w, fmt.Sprintf("Error copying MS response body: %v", err), http.StatusInternalServerError) | ||
| } | ||
| return | ||
| } | ||
|
|
||
| // Convert to google format language list and write it back | ||
| msBody, err := ioutil.ReadAll(msResp.Body) | ||
| if err != nil { | ||
| http.Error(w, fmt.Sprintf("Error reading MS response body: %v", err), http.StatusInternalServerError) | ||
| } | ||
| body, err := language.ToGoogleLanguageList(msBody) | ||
| if err != nil { | ||
| http.Error(w, fmt.Sprintf("Error converting to google language list: %v", err), http.StatusInternalServerError) | ||
| return | ||
| } | ||
| _, err = w.Write(body) | ||
| if err != nil { | ||
| log.Errorf("Error writing response body for translate requests: %v", err) | ||
| } | ||
| } | ||
|
|
||
| // Translate converts a Google format translate request into a Microsoft format | ||
| // one which will be send to the Microsoft server, and write a Google format | ||
| // response back to the client. | ||
| @@ -0,0 +1,66 @@ | ||
| package language | ||
|
|
||
| import ( | ||
| "encoding/json" | ||
| ) | ||
|
|
||
| // Language represents the format of language in Microsoft language list | ||
| // Note that nativeName and dir are not used in this package since Google | ||
| // doesn't have them. | ||
| type Language struct { | ||
| Name string `json:"name"` | ||
| } | ||
|
|
||
| // MicrosoftLanguageList represents the JSON format for Microsoft language list | ||
| // Example: | ||
| // { | ||
| // "translation": { | ||
| // "af": { | ||
| // "name": "Afrikaans", | ||
| // "nativeName": "Afrikaans", | ||
| // "dir": "ltr" | ||
| // }, | ||
| // "en": { | ||
| // "name": "English", | ||
| // "nativeName": "English", | ||
| // "dir": "ltr" | ||
| // } | ||
| // } | ||
| // } | ||
| type MicrosoftLanguageList struct { | ||
| Translation map[string]Language | ||
| } | ||
|
|
||
| // GoogleLanguageList represents the JSON format for Google language list | ||
| // Example: | ||
| // { | ||
| // "sl":{"auto":"Detect language","af":"Afrikaans"}, | ||
| // "tl":{"af": "Afrikaans", "sq": "Albanian"} | ||
| // "al":{} | ||
| // } | ||
| // Note that al is not used in this package since Microsoft don't have it. | ||
| type GoogleLanguageList struct { | ||
| Sl map[string]string `json:"sl"` | ||
| Tl map[string]string `json:"tl"` | ||
| } | ||
|
|
||
| // ToGoogleLanguageList unmarshal a MS language list and marshal a corresponding | ||
| // google language list and return it. | ||
| func ToGoogleLanguageList(body []byte) ([]byte, error) { | ||
| // Unmarshal the MS language list from the response | ||
| var msLangList MicrosoftLanguageList | ||
| err := json.Unmarshal(body, &msLangList) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| // Marshal the language list using google's format | ||
| var googleLangList GoogleLanguageList | ||
| googleLangList.Sl = make(map[string]string, len(msLangList.Translation)) | ||
| googleLangList.Tl = make(map[string]string, len(msLangList.Translation)) | ||
| for k, lang := range msLangList.Translation { | ||
| googleLangList.Sl[k] = lang.Name | ||
| googleLangList.Tl[k] = lang.Name | ||
| } | ||
| return json.Marshal(googleLangList) | ||
| } |
We unset the X-Forwarded-* headers sent to Google servers at the proxy. We should unset the headers for connection to Microsoft servers as well. See: https://github.com/brave/devops/pull/785/files#diff-e262328707cf31665d8378e0949ef286R67