0
votes

I am trying to connect to IBM Watson's speech to text WebSocket with a new account, that has IAM authorization only.

My WS endpoint is wss://stream-fra.watsonplatform.net/text-to-speech/api/v1/recognize and I get an access token via https://iam.bluemix.net/identity/token. Now when I open the socket connection with Authorization header with value Bearer token I get a bad handshake response: websocket: bad handshake, Unauthorized 401. Language is Go.

Am I doing something wrong or it is not possible to connect to Watson's speech to text WebSocket without username/password authentication i.e. the deprecated watson-token?

EDIT:

Code to open WebSocket:

headers := http.Header{}
headers.Set("Authorization", "Bearer " + access_token)
conn, resp, err := websocket.DefaultDialer.Dial("wss://stream-fra.watsonplatform.net/text-to-speech/api/v1/recognize", headers)

I have also tried basic authorization with apikey:**api_key** and the result is the same: 401.

EDIT 2:

Code to get the access token (based on the Watson Swift and Python SDKs) which succeeds and returns access and refresh tokens:

func getWatsonToken(apiKey string) (string, error) {
    // Base on the Watson Swift and Python SDKs
    // https://github.com/watson-developer-cloud/restkit/blob/master/Sources/RestKit/Authentication.swift
    // https://github.com/watson-developer-cloud/python-sdk/blob/master/watson_developer_cloud/iam_token_manager.py

    const tokenUrl = "https://iam.bluemix.net/identity/token"

    form := url.Values{}
    form.Set("grant_type", "urn:ibm:params:oauth:grant-type:apikey")
    form.Set("apikey", apiKey)
    form.Set("response_type", "cloud_iam")

    // Token from simple "http.PostForm" does not work either
    //resp, err := http.PostForm(tokenUrl, form)

    req, err := http.NewRequest(http.MethodPost, tokenUrl, nil)
    if err != nil {
        log.Printf("could not create HTTP request to get Watson token: %+v", err)
        return "", nil
    }

    header := http.Header{}
    header.Set("Content-Type", "application/x-www-form-urlencoded")
    header.Set("Accept", "application/json")
    // "Yng6Yng=" is "bx:bx"
    header.Set("Authorization", "Basic Yng6Yng=")
    req.Header = header

    req.Body = ioutil.NopCloser(bytes.NewReader([]byte(form.Encode())))

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        log.Printf("problem executing HTTP request to get Watson token: %+v", err)
        return "", err
    }

    defer resp.Body.Close()

    if resp.StatusCode != 200 {
        return "", errors.New(fmt.Sprintf("failed to get Watson token: %d", resp.StatusCode))
    }

    jsonBody, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        log.Printf("problem reading Watson token from response body: %+v", err)
    }

    tokenResponse := &struct {
        AccessToken  string `json:"access_token"`
        RefreshToken string `json:"refresh_token"`
        TokenType    string `json:"token_type"`
        ExpiresIn    int64  `json:"expires_in"`
        Expiration   int64  `json:"expiration"`
    }{}

    err = json.Unmarshal(jsonBody, tokenResponse)
    if err != nil {
        log.Printf("could not parse Watson token response: %+v", err)
        return "", err
    }

    return tokenResponse.AccessToken, err
}
1
Can you add the code here to make sure I understand what you are trying?Vidyasagar Machupalli
@VidyasagarMachupalli I have added the code.shelll

1 Answers

0
votes

I made an error in the endpoint and used the text-to-speech instead of the speech-to-text. With the correct URL the WebSocket API works.

wss://stream-fra.watsonplatform.net/text-to-speech/api/v1/recognize should be wss://stream-fra.watsonplatform.net/speech-to-text/api/v1/recognize