Сервер хоста C # возвращает ошибку 405 при попытке конвертировать из узла в C # - PullRequest
2 голосов
/ 12 октября 2019

Я пытаюсь преобразовать api узла с запросом в запросы C #. Код узла делится на два блока.

Первый блок «Аутентификация»:

const AUTHENTICATION_PATH = '/_api/authentication/sessions/usercredentials'
const BASE_URL = 'www.avanza.se'

authenticate(credentials) {
    if (!credentials) {
        return Promise.reject('Missing credentials.')
    }

    if (!credentials.username) {
        return Promise.reject('Missing credentials.username.')
    }

    if (!credentials.password) {
        return Promise.reject('Missing credentials.password.')
    }

    if (!(this._authenticationTimeout >= MIN_INACTIVE_MINUTES &&
          this._authenticationTimeout <= MAX_INACTIVE_MINUTES)) {
        return Promise.reject(`Session timeout not in range ${MIN_INACTIVE_MINUTES} - ${MAX_INACTIVE_MINUTES} minutes.`)
    }

    return new Promise((resolve, reject) => {
        const data = {
            maxInactiveMinutes: this._authenticationTimeout,
            password: credentials.password,
            username: credentials.username
        }
    request({
        method: 'POST',
        path: constants.paths.AUTHENTICATION_PATH,
        data
  }).then((response) => {
    // No second factor requested, continue with normal login
    if (typeof response.body.twoFactorLogin === 'undefined') {
      return Promise.resolve(response)
    }
    const tfaOpts = response.body.twoFactorLogin;

    if (tfaOpts.method !== 'TOTP') {
      return Promise.reject(`Unsupported second factor method ${tfaOpts.method}`)
    }
    const totpCode = (credentials.totpSecret) ? totp(credentials.totpSecret) : credentials.totp

    if (!totpCode) {
      return Promise.reject('Missing credentials.totp or credentials.totpSecret')
    }

    return request({
      method: 'POST',
      path: constants.paths.TOTP_PATH,
      data: {
        method: 'TOTP',
        totpCode
      },
      headers: {
        Cookie: `AZAMFATRANSACTION=${tfaOpts.transactionId}`
      }
    })
  }).then((response) => {
    this._authenticated = true
    this._credentials = credentials
    this._securityToken = response.headers['x-securitytoken']
    this._authenticationSession = response.body.authenticationSession
    this._pushSubscriptionId = response.body.pushSubscriptionId
    this._customerId = response.body.customerId

    // Re-authenticate after timeout minus one minute
    this._scheduleReauth((this._authenticationTimeout - 1) * 60 * 1000)

    if (this._socket) {
      this._socketRestart()
    }

    resolve({
      securityToken: this._securityToken,
      authenticationSession: this._authenticationSession,
      pushSubscriptionId: this._pushSubscriptionId,
      customerId: this._customerId
    })
  }).catch((e) => {
    this._pushSubscriptionId = undefined
    reject(e)
  })
})
}

Второй блок с запросом:

function request(options) {
    if (!options) {
        return Promise.reject('Missing options.')
    }

    const data = JSON.stringify(options.data)

    return new Promise((resolve, reject) => {
        const req = https.request({
            host: BASE_URL,
            port: 443,
            method: options.method,
            path: options.path,
            headers: Object.assign({
                'Accept': '*/*',
                'Content-Type': 'application/json',
                'User-Agent': USER_AGENT,
                'Content-Length': data.length
            }, options.headers)
        }, (response) => {
            const body = []
            response.on('data', chunk => body.push(chunk))
            response.on('end', () => {
                let parsedBody = body.join('')

                try {
                   parsedBody = JSON.parse(parsedBody)
                } catch (e) {
                   debug('Received non-JSON data from API.', body)
                }

                const res = {
                   statusCode: response.statusCode,
                   statusMessage: response.statusMessage,
                   headers: response.headers,
                   body: parsedBody
                }

                if (response.statusCode < 200 || response.statusCode > 299) {
                    reject(res)
                } else {
                    resolve(res)
                }
            })
        })

        if (data) {
           req.write(data)
        }

        req.on('error', e => reject(e))
        req.end()
    })
}

Теперь моя реализация C #:

var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://www.avanza.se/_api/authentication/sessions/usercredentials");

httpWebRequest.ContentType = "application/json";
httpWebRequest.Host = "www.avanza.se";
httpWebRequest.Method = "POST";
httpWebRequest.Accept = "*/*";
httpWebRequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36";
httpWebRequest.Timeout = 3000;

Holdern korv = new Holdern()
        {
            maxInactiveMinutes = 30,
            username = "usernamestring",
            password = "passwordstring"
        };

string json = JsonConvert.SerializeObject(korv);
httpWebRequest.ContentLength = json.Length;

using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
    streamWriter.Write(json);
}

var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();

using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
    var result = streamReader.ReadToEnd();
}

Проблема в том, что я получаю ошибку 405. Чего мне не хватает?

Но если я вручную сделаю это с почтальоном, это выдаст мне 500 ошибок. Кто-нибудь, кто может определить, что не так?

Карл

...