Java 11 HttpClient не отправляет базовую аутентификацию

Реализация этого как генератора делает его довольно приятным для работы. Обратите внимание: эта реализация отличается от той, которая требует, чтобы весь входной массив сначала перетасовался.

Эта функция sample работает лениво, предоставляя вам 1 случайный элемент за итерацию до N предметов, которые вы запрашиваете. Это хорошо, потому что, если вам просто нужно 3 элемента из списка 1000, сначала вам не нужно касаться всех 1000 элементов.

blockquote>

// sample :: Integer -> [a] -> [a]
const sample = n => function* (xs) {
  let ys = xs.slice(0);
  let len = xs.length;
  while (n > 0 && len > 0) {
    let i = (Math.random() * len) >> 0;
    yield ys.splice(i,1)[0];
    n--; len--;
  }
}

// example inputs
let items = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
let numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

// get 3 random items
for (let i of sample(3) (items))
  console.log(i); // f g c

// partial application
const lotto = sample(3);
for (let i of lotto(numbers))
  console.log(i); // 3 8 7

// shuffle an array
const shuffle = xs => Array.from(sample (Infinity) (xs))
console.log(shuffle(items)) // [b c g f d e a]

Я решил реализовать sample способом, который не мутирует входной массив, но вы можете легко утверждать, что мутирующая реализация благоприятна.

Например, shuffle функция может захотеть изменить исходный массив ввода. Или вы можете попробовать с одного и того же входа в разное время, каждый раз обновляя вход.

// sample :: Integer -> [a] -> [a]
const sample = n => function* (xs) {
  let len = xs.length;
  while (n > 0 && len > 0) {
    let i = (Math.random() * len) >> 0;
    yield xs.splice(i,1)[0];
    n--; len--;
  }
}

// deal :: [Card] -> [Card]
const deal = xs => Array.from(sample (2) (xs));

// setup a deck of cards (13 in this case)
// cards :: [Card]
let cards = 'A234567890JQK'.split('');

// deal 6 players 2 cards each
// players :: [[Card]]
let players = Array.from(Array(6), $=> deal(cards))

console.log(players);
// [K, J], [6, 0], [2, 8], [Q, 7], [5, 4], [9, A]

// `cards` has been mutated. only 1 card remains in the deck
console.log(cards);
// [3]

sample больше не чистая функция из-за входной мутации массива, но в определенных обстоятельствах (продемонстрировано выше) это может иметь больше смысла.


Еще одна причина, по которой я выбрал генератор вместо функции, которая просто возвращает массив, потому что вы можете продолжить выборку до определенного условия.

Возможно, я хочу, чтобы первое простое число из списка из 1 000 000 случайных чисел.

  • «Сколько должен ли я пробовать? » - вам не нужно указывать
  • « Должен ли я сначала найти все простые числа, а затем выбрать случайное число? » - Нет.

Поскольку мы работаем с генератором, эта задача тривиальна

const randomPrimeNumber = listOfNumbers => {
  for (let x of sample(Infinity) (listOfNumbers)) {
    if (isPrime(x))
      return x;
  }
  return NaN;
}

Это будет непрерывно отображать 1 случайное число за раз, x , проверьте, является ли он простым, а затем возвратите x, если это так. Если список чисел исчерпан до того, как найдено штрих, возвращается NaN.


Примечание:

Этот ответ был первоначально разделен по другому вопросу, который был закрыт как дубликат этого. Поскольку он сильно отличается от других предлагаемых здесь решений, я решил поделиться им и здесь

5
задан Naman 16 January 2019 в 01:11
поделиться

1 ответ

Служба, которую я вызывал (в данном случае Jira Cloud API от Atlassian), поддерживает как базовую, так и OAuth-аутентификацию. Я пытался использовать HTTP Basic, но он отправляет вызов аутентификации для OAuth.

Начиная с текущего JDK 11, HttpClient не отправляет базовые учетные данные, пока их не вызовут с помощью заголовка WWW-Authenticate с сервера. Кроме того, единственный тип вызова, который он понимает, - это обычная проверка подлинности. Соответствующий код JDK находится здесь (в комплекте с TODO для поддержки не только базовой аутентификации), если вы хотите взглянуть.

Тем временем я решил обойти API аутентификации HttpClient, а также сам создать и отправить заголовок Basic Authorization:

public static void main(String[] args) {
    var client = HttpClient.newBuilder()
            .version(HttpClient.Version.HTTP_1_1)
            .build();
    var request = HttpRequest.newBuilder()
            .uri(new URI("https://service-that-needs-auth.example/"))
            .header("Authorization", basicAuth("username", "password"))
            .build();
    client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
            .thenApply(HttpResponse::body)
            .thenAccept(System.out::println)
            .join();
}

private static String basicAuth(String username, String password) {
    return "Basic " + Base64.getEncoder().encodeToString((username + ":" + password).getBytes());
}
0
ответ дан Eugene 16 January 2019 в 01:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: