2016-10-02 5 views
1

Я постараюсь сохранить это как краткое и максимально возможное.Потребление API REST в Ruby - Когда аутентифицировать?

Я пишу драгоценный камень Ruby, смоделированный после драгоценного камня Diplomat, который является оберткой API REST продукта. API, который я использую, использует аутентификацию на основе токенов; маркер API отправляется через POST, а сеанс возвращается как файл cookie. Я использую промежуточное ПО Faraday cookiejar для обработки файлов cookie, возвращаемых API. Проблема, с которой я борюсь, концептуально - это когда аутентифицироваться.

У меня есть два класса, один называется RestClient и один называется Volume; последний наследует от первого. В настоящее время метод initClient RestClient создает объект подключения и проверяет подлинность, в то время как метод init Volume вызывает супер и передает путь. Мое мышление здесь состоит в том, что когда любой класс, который наследует от RestClient, инициализируется, он аутентифицирует пользователя.

class RestClient 
    def initialize(api_path) 
    <build connection> 
    auth 
    end 
    def auth 
    <post token, get session cookie> 
    end 
end 

class Volume < RestClient 
    def initialize 
    super('/volume') 
    end 
    def volumes 
    <send GET, receive volumes> 
    end 
end 

obj = Volume.new #Creates object, authenticates user 
obj.volumes #Returns list of volumes 

Я думаю, мой вопрос: .. я направился по правому пути? Должен ли я проводить аутентификацию до тех пор, пока метод сначала не вызовет объект, а не аутентифицируется, когда он инициализируется? Неужели я об этом совершенно неправильно?

ответ

0

Что вы здесь задаете, это скорее вопрос в стиле кода. здесь нет правильного или неправильного. я собирался проголосовать, чтобы закрыть, потому что я думаю, что это primarily opinion-based.

, так как у меня есть мнение, вместо этого я пишу ответ.

а) не слишком думать

просто реализовать вещи, если это работает, достаточно хорошо

б) правило 3

если вы реализовали 3 вещи одного и того же вид и шаблон появляется, рефактор!

с) отказаться от использования уделом

в случае сомнений, не используйте наследование. модуль будет достаточно хорош в большинстве случаев.

на ваш вопрос конкретно:

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

Что бы я хотел сделать, это просто реализовать все, что вам нужно, простыми методами.

что не так с вызовом authenticate перед тем, как сделать еще один звонок? поместив его в блок может сделать это очень красиво и читаемым:

client.authenticate do |session| 
    session.volumes 
end 

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

+0

Я ценю обратную связь, я очень склонен к overthinking. Я ходил с ленивой аутентификацией перед каждым методом, который вызывает вызов API, что впоследствии упростило тестирование. Я собираюсь отметить это, поскольку ответ на тот простой факт, что указание на аутентификацию во время инициализации является плохим примером, и этот совет был большой помощью. – Alayde

0

Является ли cookie единственным, поддерживающим ваш API? Очень часто серверные (сервер-серверные) API-интерфейсы REST также реализуют лучшие стратегии аутентификации, которые позволяют вам проходить авторизацию с каждым запросом.

Все, что было сказано, что вы также можете сделать что-то вроде этого:

client = MyApi::Client.for_user(username: ..., password: ....) 
#...or 
client = MyApi::Client.for_token(token) 
volumes = MyApi::Volumes.get(client: client) 

Таким образом, для того, где авторизация требуется вам будет делать хорошую вещь, «поощряя ваш класс использовать право» - что вы просто не будете создавать экземпляр клиента без данных аутентификации и не будете инициализировать ваши удаленные объекты/вызовы без клиента.

Затем, в клиенте, что вы можете сделать, это memoized аутентификации по первому требованию

def perform(http_method, url, ...) 
    @auth_cookie ||= @client.get_cookie_by_authentication 
    ... 
end 
Смежные вопросы