1- //! ` LinkedIn` URL validation library
1+ //! LinkedIn profile URL validation library.
22//!
3- //! This library provides tools to validate `LinkedIn` profile URLs,
4- //! checking both format correctness and profile existence.
3+ //! This crate provides tools to validate LinkedIn profile URLs by checking both
4+ //! format correctness and profile existence through HTTP requests.
5+ //!
6+ //! # Features
7+ //!
8+ //! - Format validation without network calls
9+ //! - Profile existence verification
10+ //! - Async and sync APIs
11+ //! - Rate limiting awareness
12+ //!
13+ //! # Examples
14+ //!
15+ //! ## Basic usage
16+ //!
17+ //! ```no_run
18+ //! use linkedin_profile_validator::{LinkedInValidator, LinkedInUrlError};
19+ //!
20+ //! let validator = LinkedInValidator::new();
21+ //! match validator.is_valid_linkedin_profile_url("https://www.linkedin.com/in/johndoe") {
22+ //! Ok(_) => println!("Profile exists!"),
23+ //! Err(LinkedInUrlError::ProfileNotFound) => println!("Profile not found"),
24+ //! Err(LinkedInUrlError::AuthenticationRequired) => println!("LinkedIn requires auth"),
25+ //! Err(e) => println!("Error: {}", e),
26+ //! }
27+ //! ```
28+ //!
29+ //! ## Format validation only
30+ //!
31+ //! ```
32+ //! use linkedin_profile_validator::is_valid_linkedin_profile_format;
33+ //!
34+ //! if is_valid_linkedin_profile_format("https://www.linkedin.com/in/johndoe") {
35+ //! println!("Valid LinkedIn profile URL format");
36+ //! }
37+ //! ```
538
639use regex:: Regex ;
740use thiserror:: Error ;
841use url:: Url ;
942
43+ /// Errors that can occur during LinkedIn URL validation.
1044#[ derive( Error , Debug ) ]
1145pub enum LinkedInUrlError {
46+ /// The provided URL has invalid format.
1247 #[ error( "Invalid URL format: {0}" ) ]
1348 InvalidUrl ( String ) ,
1449
50+ /// The URL is not from LinkedIn domain.
1551 #[ error( "Not a LinkedIn URL" ) ]
1652 NotLinkedInUrl ,
1753
54+ /// The URL is from LinkedIn but not a profile URL.
1855 #[ error( "Not a LinkedIn profile URL" ) ]
1956 NotProfileUrl ,
2057
58+ /// Network error occurred during validation.
2159 #[ error( "Network error: {0}" ) ]
2260 NetworkError ( #[ from] reqwest:: Error ) ,
2361
62+ /// The LinkedIn profile was not found (404).
2463 #[ error( "Profile not found (404)" ) ]
2564 ProfileNotFound ,
2665
66+ /// LinkedIn requires authentication to verify the profile.
2767 #[ error( "Unable to verify - LinkedIn requires authentication" ) ]
2868 AuthenticationRequired ,
2969}
3070
71+ /// A LinkedIn profile validator that performs HTTP requests to verify profile existence.
72+ ///
73+ /// # Example
74+ ///
75+ /// ```no_run
76+ /// use linkedin_profile_validator::LinkedInValidator;
77+ ///
78+ /// let validator = LinkedInValidator::new();
79+ /// let result = validator.is_valid_linkedin_profile_url("https://www.linkedin.com/in/johndoe");
80+ /// ```
3181pub struct LinkedInValidator {
3282 client : reqwest:: blocking:: Client ,
3383}
3484
3585impl LinkedInValidator {
36- /// Creates a new ` LinkedIn` validator instance.
86+ /// Creates a new LinkedIn validator instance.
3787 ///
3888 /// # Panics
3989 ///
@@ -49,16 +99,40 @@ impl LinkedInValidator {
4999 Self { client }
50100 }
51101
52- /// Validates a `LinkedIn` profile URL by checking format and existence.
102+ /// Validates a LinkedIn profile URL by checking format and existence.
103+ ///
104+ /// This method performs an HTTP request to verify if the profile actually exists.
105+ ///
106+ /// # Arguments
107+ ///
108+ /// * `url_str` - The LinkedIn profile URL to validate
109+ ///
110+ /// # Returns
111+ ///
112+ /// * `Ok(true)` - If the profile exists
113+ /// * `Err(LinkedInUrlError)` - If validation fails
53114 ///
54115 /// # Errors
55116 ///
56117 /// Returns an error if:
57118 /// - The URL format is invalid
58- /// - The URL is not from ` LinkedIn` domain
119+ /// - The URL is not from LinkedIn domain
59120 /// - The URL is not a profile URL
60121 /// - Network request fails
61122 /// - The profile doesn't exist (404)
123+ /// - LinkedIn requires authentication
124+ ///
125+ /// # Example
126+ ///
127+ /// ```no_run
128+ /// use linkedin_profile_validator::LinkedInValidator;
129+ ///
130+ /// let validator = LinkedInValidator::new();
131+ /// match validator.is_valid_linkedin_profile_url("https://www.linkedin.com/in/johndoe") {
132+ /// Ok(_) => println!("Valid profile"),
133+ /// Err(e) => println!("Invalid: {}", e),
134+ /// }
135+ /// ```
62136 pub fn is_valid_linkedin_profile_url ( & self , url_str : & str ) -> Result < bool , LinkedInUrlError > {
63137 let url = Url :: parse ( url_str) . map_err ( |e| LinkedInUrlError :: InvalidUrl ( e. to_string ( ) ) ) ?;
64138
@@ -131,20 +205,42 @@ impl Default for LinkedInValidator {
131205 }
132206}
133207
134- /// Validates a `LinkedIn` profile URL asynchronously.
208+ /// Validates a LinkedIn profile URL asynchronously.
209+ ///
210+ /// This function performs an HTTP request to verify if the profile actually exists.
211+ /// Use this for async contexts like web servers.
212+ ///
213+ /// # Arguments
214+ ///
215+ /// * `url` - The LinkedIn profile URL to validate
216+ ///
217+ /// # Returns
218+ ///
219+ /// * `Ok(true)` - If the profile exists
220+ /// * `Err(LinkedInUrlError)` - If validation fails
135221///
136222/// # Errors
137223///
138224/// Returns an error if:
139225/// - The URL format is invalid
140- /// - The URL is not from ` LinkedIn` domain
226+ /// - The URL is not from LinkedIn domain
141227/// - The URL is not a profile URL
142228/// - Network request fails
143229/// - The profile doesn't exist (404)
230+ /// - LinkedIn requires authentication
231+ ///
232+ /// # Example
144233///
145- /// # Panics
234+ /// ```no_run
235+ /// use linkedin_profile_validator::validate_linkedin_url_async;
146236///
147- /// Panics if the regex pattern is invalid (this should never happen).
237+ /// # async fn example() {
238+ /// match validate_linkedin_url_async("https://www.linkedin.com/in/johndoe").await {
239+ /// Ok(_) => println!("Valid profile"),
240+ /// Err(e) => println!("Invalid: {}", e),
241+ /// }
242+ /// # }
243+ /// ```
148244pub async fn validate_linkedin_url_async ( url : & str ) -> Result < bool , LinkedInUrlError > {
149245 let url_parsed = Url :: parse ( url) . map_err ( |e| LinkedInUrlError :: InvalidUrl ( e. to_string ( ) ) ) ?;
150246
@@ -197,11 +293,29 @@ pub async fn validate_linkedin_url_async(url: &str) -> Result<bool, LinkedInUrlE
197293 Ok ( true )
198294}
199295
200- /// Checks if a URL has valid `LinkedIn` profile format (no network calls).
296+ /// Checks if a URL has valid LinkedIn profile format without making network calls.
297+ ///
298+ /// This function only validates the URL format and does not check if the profile exists.
299+ /// Use this for quick validation without network overhead.
300+ ///
301+ /// # Arguments
302+ ///
303+ /// * `url` - The URL to validate
201304///
202- /// # Panics
305+ /// # Returns
203306///
204- /// Panics if the regex pattern is invalid (this should never happen).
307+ /// * `true` - If the URL has valid LinkedIn profile format
308+ /// * `false` - If the URL is invalid or not a LinkedIn profile URL
309+ ///
310+ /// # Example
311+ ///
312+ /// ```
313+ /// use linkedin_profile_validator::is_valid_linkedin_profile_format;
314+ ///
315+ /// assert!(is_valid_linkedin_profile_format("https://www.linkedin.com/in/johndoe"));
316+ /// assert!(!is_valid_linkedin_profile_format("https://www.google.com/in/johndoe"));
317+ /// assert!(!is_valid_linkedin_profile_format("https://linkedin.com/company/microsoft"));
318+ /// ```
205319#[ must_use]
206320pub fn is_valid_linkedin_profile_format ( url : & str ) -> bool {
207321 let Ok ( url_parsed) = Url :: parse ( url) else {
@@ -254,7 +368,10 @@ mod tests {
254368 match validator. is_valid_linkedin_profile_url ( "https://www.linkedin.com/in/hamze/" ) {
255369 Ok ( true ) => ( ) ,
256370 Ok ( false ) => panic ! ( "Expected profile to be valid" ) ,
257- Err ( e) => panic ! ( "Expected profile to be valid, got error: {e}" ) ,
371+ Err ( LinkedInUrlError :: AuthenticationRequired ) => {
372+ println ! ( "LinkedIn requires authentication - cannot verify profile existence" ) ;
373+ }
374+ Err ( e) => panic ! ( "Expected profile to be valid or require auth, got error: {e}" ) ,
258375 }
259376 }
260377
@@ -284,7 +401,10 @@ mod tests {
284401 match validate_linkedin_url_async ( "https://www.linkedin.com/in/hamze/" ) . await {
285402 Ok ( true ) => ( ) ,
286403 Ok ( false ) => panic ! ( "Expected profile to be valid" ) ,
287- Err ( e) => panic ! ( "Expected profile to be valid, got error: {e}" ) ,
404+ Err ( LinkedInUrlError :: AuthenticationRequired ) => {
405+ println ! ( "LinkedIn requires authentication - cannot verify profile existence" ) ;
406+ }
407+ Err ( e) => panic ! ( "Expected profile to be valid or require auth, got error: {e}" ) ,
288408 }
289409 }
290410
0 commit comments