use http::header::{ACCEPT, CONTENT_TYPE};
use http::StatusCode;
use url::Url;
use crate::http::CONTENT_TYPE_FORM_URLENCODED;
use crate::standards::websub::{Result, WebSubError};
#[derive(Debug, Clone)]
pub struct PublishResponse {
pub status: StatusCode,
}
#[tracing::instrument(skip(client))]
pub async fn publish(
client: &impl crate::http::Client,
hub: &Url,
topic: &Url,
) -> Result<PublishResponse> {
let body = url::form_urlencoded::Serializer::new(String::new())
.append_pair("hub.mode", "publish")
.append_pair("hub.url", topic.as_str())
.finish();
let request = http::Request::builder()
.method(http::Method::POST)
.uri(hub.as_str())
.header(ACCEPT, "*/*")
.header(CONTENT_TYPE, CONTENT_TYPE_FORM_URLENCODED)
.body(crate::http::Body::Bytes(body.into_bytes()))
.map_err(|err| WebSubError::Http(err.to_string()))?;
let response = client.send_request(request).await.map_err(|err| WebSubError::Network(Box::new(err)))?;
let status = response.status();
if status == http::StatusCode::ACCEPTED || status == http::StatusCode::NO_CONTENT || status == http::StatusCode::OK {
Ok(PublishResponse { status })
} else {
Err(WebSubError::Http(format!("Hub rejected publish request: {}", status)))
}
}